{"id":15452970,"url":"https://github.com/terichadbourne/unscheduler-backend","last_synced_at":"2026-04-17T05:02:31.644Z","repository":{"id":115302461,"uuid":"143731788","full_name":"terichadbourne/unscheduler-backend","owner":"terichadbourne","description":"RESTful API for the Unscheduler app, built with Ruby on Rails and PostgreSQL","archived":false,"fork":false,"pushed_at":"2018-08-10T04:46:19.000Z","size":1378,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-11T11:34:16.040Z","etag":null,"topics":["api","postgresql","rest-api","ruby-on-rails"],"latest_commit_sha":null,"homepage":"https://sleepy-springs-55525.herokuapp.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terichadbourne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-06T13:22:25.000Z","updated_at":"2021-03-21T22:45:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"0a1f998e-3228-4c10-bdc6-b507767f3f19","html_url":"https://github.com/terichadbourne/unscheduler-backend","commit_stats":{"total_commits":12,"total_committers":1,"mean_commits":12.0,"dds":0.0,"last_synced_commit":"345d2117b061569110f2a003cde8d5264e4c51af"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/terichadbourne/unscheduler-backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terichadbourne%2Funscheduler-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terichadbourne%2Funscheduler-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terichadbourne%2Funscheduler-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terichadbourne%2Funscheduler-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terichadbourne","download_url":"https://codeload.github.com/terichadbourne/unscheduler-backend/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terichadbourne%2Funscheduler-backend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31915900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","postgresql","rest-api","ruby-on-rails"],"created_at":"2024-10-01T21:57:38.763Z","updated_at":"2026-04-17T05:02:31.612Z","avatar_url":"https://github.com/terichadbourne.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unscheduler: An unconference scheduling tool\n\nThe Unscheduler is an app for managing the voting and scheduling process for\nunconferences, inspired by my work as a co-organizer for [Offline Camp](http://offlinefirst.org/camp). *(Yes, [unconferences have schedules](https://medium.com/offline-camp/crafting-community-events-that-leave-them-wanting-smore-902974cff4d4)!)*\n\n**Check out the code or the [live app](https://terichadbourne.com/unscheduler-ember/)!**\n\n* Front-end client\n   * [GitHub repo](https://github.com/terichadbourne/unscheduler-ember) (unscheduler-ember)\n   * [Live site](https://terichadbourne.com/unscheduler-ember/) (deployed on GitHub Pages)\n* Back-end API\n   * [GitHub repo](https://github.com/terichadbourne/unscheduler-backend) (unscheduler-backend)\n   * [Live site](https://sleepy-springs-55525.herokuapp.com/) (deployed on Heroku)\n\n## Technologies used\n\n### Front-End Technologies\n- Ember\n- Handlebars\n- JavaScript\n- jQuery\n- Bootstrap\n- HTML5\n- CSS3\n- Sass\n\n### Back-End Technologies\n- Ruby on Rails\n- PostgreSQL\n- Active Record\n\n## Screenshots\n\n#### Discussion Proposals\n\u003cimg src=\"public/images/ScreenshotProposals.png\" width=\"500\"\u003e\n\n#### Admin Panel\n\u003cimg src=\"public/images/ScreenshotAdminPanel.png\" width=\"500\"\u003e\n\n## The backstory: Unconference organizing with sticky notes and Mr. Sketch markers\n\nAs a member of the [Offline First](http://offlinefirst.org) development\ncommunity, I co-organize an unconference called [Offline Camp](http://offlinefirst.org/camp), where attendees propose topics for\ndiscussion and then vote to determine what topics are actually discussed in the\nlimited time we have available. As organizers, we take the votes (a sticky note\nfor each proposal, with stickers representing votes won) and give some careful\nthought to how to best schedule the winning sessions so that the most popular\nones are spread across different timeslots from each other and in the largest\navailable rooms, topics that should appeal to similar subgroups of attendees\naren't scheduled to conflict with one another, etc.\n\n#### Voting on proposed discussion topics with sticky notes and stickers\n\u003cimg src=\"public/images/AnalogVoting.png\" width=\"400\"\u003e\n\n#### Scheduling the winners on a grid of available session slots\n\u003cimg src=\"public/images/AnalogScheduling.jpeg\" width=\"400\"\u003e\n\n## Project planning and strategy\n\nFor my first experience with Ember, I decided to return to the Unscheduler app\nthat I had previously built in jQuery and work on some new functionality. Since\nevent admins make decisions that affect what all users see when they visit the\nsite (proposals, voting, or final schedule), this seemed like a natural use case\nfor view states. With only 4 days available to update my Ruby on Rails API and\nrework the front end in Ember and Handlebars, prioritization was key.\n\n### Features\n\nHere's a look at the current and future features of the Unschedulur app. (Note than many actions are restricted to admin users.)\n\nFeature | User Access | Completion Status\n--- | --- | ---\nSet event name and max votes per person | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[ ] Participants\u003c/li\u003e\u003c/ul\u003e |\u003cul\u003e\u003cli\u003e[x] jQuery\u003c/li\u003e\u003cli\u003e[x] Ember\u003c/li\u003e\u003c/ul\u003e\nSet event status (proposing, voting, schedule final) | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[x] Participants\u003c/li\u003e\u003c/ul\u003e | \u003cul\u003e\u003cli\u003e[x] jQuery\u003c/li\u003e\u003cli\u003e[x] Ember\u003c/li\u003e\u003c/ul\u003e\nPropose discussion topics | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[x] Participants\u003c/li\u003e\u003c/ul\u003e|\u003cul\u003e\u003cli\u003e[x] jQuery\u003c/li\u003e\u003cli\u003e[x] Ember\u003c/li\u003e\u003c/ul\u003e\nVote on discussion topics  | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[x] Participants\u003c/li\u003e\u003c/ul\u003e|\u003cul\u003e\u003cli\u003e[x] jQuery\u003c/li\u003e\u003cli\u003e[ ] Ember\u003c/li\u003e\u003c/ul\u003e\nCalculate winning sessions  | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[ ] Participants\u003c/li\u003e\u003c/ul\u003e |\u003cul\u003e\u003cli\u003e[x] jQuery\u003c/li\u003e\u003cli\u003e[ ] Ember\u003c/li\u003e\u003c/ul\u003e\nBuild placeholder schedule with rooms and timeslots  | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[ ] Participants\u003c/li\u003e\u003c/ul\u003e |\u003cul\u003e\u003cli\u003e[ ] jQuery\u003c/li\u003e\u003cli\u003e[x] Ember\u003c/li\u003e\u003c/ul\u003e\nAssign discussion topics to session slots | \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[ ] Participants\u003c/li\u003e\u003c/ul\u003e |\u003cul\u003e\u003cli\u003e[ ] jQuery\u003c/li\u003e\u003cli\u003e[ ] Ember\u003c/li\u003e\u003c/ul\u003e\nView final schedule (beta - timeslots only)| \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[x] Participants\u003c/li\u003e\u003c/ul\u003e |\u003cul\u003e\u003cli\u003e[ ] jQuery\u003c/li\u003e\u003cli\u003e[x] Ember\u003c/li\u003e\u003c/ul\u003e\nView final schedule (improved formatting with discussions assigned)| \u003cul\u003e\u003cli\u003e[x] Organizers\u003c/li\u003e\u003cli\u003e[x] Participants\u003c/li\u003e\u003c/ul\u003e |\u003cul\u003e\u003cli\u003e[ ] jQuery\u003c/li\u003e\u003cli\u003e[ ] Ember\u003c/li\u003e\u003c/ul\u003e\n\n_Curious to see the previous implementation of this app? You can find more info [here](https://github.com/terichadbourne/unscheduler-client)._\n\n#### Next Steps\n- Improve update process for timeslots so an admin can make their edits from a view showing just room names and times, with their requested changes implemented across all sessions in the room or timeslot whose name has changed.\n- Add discussions to timeslots through drag and drop.\n- Improve the schedule display to sort by time and room.\n- Add room capacities to timeslot records so event organizers can assign the discussion topics with the highest vote count to the largest rooms.\n- Rebuild voting and winner selection functionality in Ember.\n\n\n### Entity Relationship Diagrams\n\nI created the following entity relationship diagrams to map out my relational database structure before revising my API, and adjusted the plan to meet time constraints on the project.\n\n- [Entity Relationship Diagrams](https://www.dropbox.com/s/x9k7nurwohfvpw4/ERD.JPG?dl=0)\n- [CRUD Actions by Resource](https://www.dropbox.com/s/4hnei17ui9de6nw/CRUD.JPG?dl=0)\n\n### API Routes\n\nMy API follows RESTful conventions with resources accessible as follows:\n\n##### Authentication\n\n| Verb   | URI Pattern            | Controller#Action |\n|--------|------------------------|-------------------|\n| POST   | `/sign-up`             | `users#signup`    |\n| POST   | `/sign-in`             | `users#signin`    |\n| PATCH  | `/change-password`     | `users#changepw`  |\n| DELETE | `/sign-out`            | `users#signout`   |\n\n##### Users\n\n| Verb | URI Pattern | Controller#Action |\n|------|-------------|-------------------|\n| GET  | `/users`    | `users#index`     |\n| GET  | `/users/1`  | `users#show`      |\n| PATCH| `/users/1`  | `users#update`    |\n\n##### Discussions\n\n| Verb | URI Pattern | Controller#Action |\n|------|-------------|-------------------|\n| GET  | `/discussions`    | `discussions#index`     |\n| GET  | `/discussions/1`  | `discussions#show`      |\n| POST   | `/discussions`   | `discussions#create`    |\n| PATCH| `/discussions/1`  | `discussions#update`    |\n| DELETE | `/discussions`   | `discussions#destroy`   |\n\n##### Votes\n\n| Verb | URI Pattern | Controller#Action |\n|------|-------------|-------------------|\n| GET  | `/votes`    | `votes#index`     |\n| GET  | `/votes/1`  | `votes#show`      |\n| POST   | `/votes`   | `votes#create`    |\n| DELETE | `/votes`   | `votes#destroy`   |\n\n##### Timeslots\n\n| Verb | URI Pattern | Controller#Action |\n|------|-------------|-------------------|\n| GET  | `/timeslots`    | `timeslots#index`     |\n| GET  | `/timeslots/1`  | `timeslots#show`      |\n| POST s | `/timeslots`   | `timeslots#create`    |\n| PATCH | `/timeslots/1`  | `timeslots#update`    |\n| DELETE | `/timeslots`   | `timeslots#destroy`   |\n\n##### Events\n\n| Verb | URI Pattern | Controller#Action |\n|------|-------------|-------------------|\n| GET  | `/events`    | `events#index`     |\n| GET  | `/events/1`  | `events#show`      |\n| PATCH| `/events/1`  | `events#update`    |\n\n\n### User Stories\n\nThese user stories guided my development process for both versions of the project:\n\n- **Proposing**\n   - As an event attendee or organizer, I want to see a list of all currently proposed sessions so that I don't create a duplicate proposal.\n   - As an event attendee or organizer, after seeing other proposals, I then want to propose a new unconference session topic for everyone to vote on so that my favorite topic will be covered.\n\n- **Voting**\n   - As an event organizer, I want control how many votes each attendee is allowed.\n   - As an event attendee or organizer, I want to see a list of all proposed sessions so that I can choose how to use my X number of votes.\n   - As an event attendee or organizer, I want to apply my X number of votes to my favorite sessions (either all to one or one/some to multiple) so that my favorite topics are likely to be selected.\n\n- **Scheduling**\n   - As an event organizer, I want to view all proposed sessions ordered by vote count to determine which are the winners.\n   - As an event organizer, I want to add some keywords (such as UX) to winning sessions to help guide my timeslot assignments, ensuring similar sessions aren't scheduled on top of each other.\n   - As an event organizer, I want to add a list of daily timeslots avialable for sessions to create my base schedule.\n   - As an event organizer, I want to add a list of rooms available for discussion sessions to create my base schedule.\n   - As an event organizer, I want to assign each winning session to an available timeslot and room so attendees can see their options.\n   - As an event attendee or organizer, I want to see today's sessions by time, with room indicated for each so I know where to be when.\n\n### Wireframes\n\nThese wireframes guided my front-end development for the Ember client:\n\n- [Wireframe: Proposing Topics](https://www.dropbox.com/s/ilzjq21ivk9fux2/Wireframe_1_Proposing.JPG?dl=0)\n- [Wireframe: Admin Panel](https://www.dropbox.com/s/1kuw85esjv0h5p5/Wireframe_4_Admin_Assorted.JPG?dl=0)\n- [Wireframe: Final Schedule](https://www.dropbox.com/s/jio0qevf7ddwjak/Wireframe_3_Schedule.JPG?dl=0)\n- [Wireframe: Voting](https://www.dropbox.com/s/xe6uwt8r28fxd27/Wireframe_2_Voting.JPG?dl=0)\n- [Wireframe: Admin Session Scheduling](https://www.dropbox.com/s/whapg3cirhbfz1m/Wireframe_5_Admin_Scheduling.JPG?dl=0) (future enhancement: add discussions to timeslots with drag and drop)\n- [Wireframe: Final Schedule](https://www.dropbox.com/s/jio0qevf7ddwjak/Wireframe_3_Schedule.JPG?dl=0)\n\n\n### Work Process\n\nI took a methodical approach to development of the app, first building out each\nPostgreSQL table and getting my Rails server up and running via curl scripts before\nadding the related front-end functionality. Here's a look at my work plan.\n\n**Setup**\n* Copy my old Rails app and deploy on a new Heroku server so I can add functionality without breaking the first version\n* Create a brand new Ember app from the template and deploy to GH pages after re-naming everything properly\n\n**MVP**\n* Pick Option A or B for new scheduling functionality with advice from instructors\n* API: Test old resources through curl scripts\n* API: Add \"timeslots\" resource, adjust other resources as needed, and test with curl scripts\n* API (IF USING OPTION B): Add \"assignments\" join table, adjust other resources as needed, and test with curl scripts\n* Client: Re-implement scheduling, voting, and existing admin functions in Ember\n* Client: Implement admin confirming winning sessions, updating records as needed based on Option A or Option B\n* Client: Implement assigning winning sessions to timeslots (with drag-and-drop if I'm getting it easily, otherwise switch to simpler solution and come back to this)\n* Style, debug, deploy\n\n**Stretch Goal # 1: Drag and Drop**\n* Client: Circle back to drag-and-drop if not completed already\n* Style, debug, deploy\n\n**Stretch Goal #2: Room Capacities**\n* API: Add room capacities to timeslot records, update and test with curl scripts\n* Client: Display both room capacities and vote counts during assignment process\n* Style, debug, deploy\n\n**Stretch Goal #3: Display Names**\n* API: Add display names to user records, update and test with curl scripts\n* Client: Display friendly username in nav and potentially on discussion listings\n* Style, debug, deploy\n\n- [Options A \u0026 B and stretch goals](https://www.dropbox.com/s/g9yzcoqiul4omjq/Plans_and_Stretch_Goals.JPG?dl=0)\n\n### Installation\n\n**To serve the back end locally:**\n- Fork and clone the [back-end repository](https://github.com/terichadbourne/unscheduler-backend).\n- Install dependencies with `bundle install`.\n- Commit your changes.\n- Create a .env for sensitive settings (`touch .env`).\n- Generate new development and test secrets (`bundle exec rails secret`) and\nstore them in `.env` with keys `SECRET_KEY_BASE_DEVELOPMENT` and `SECRET_KEY_BASE_TEST`.\n- Run the local API server at `http://localhost:4741/events` with `bin/rails server` or `bundle exec rails server`.\n\n**To run the client app locally:**\n- Fork and clone the [client repository](https://github.com/terichadbourne/unscheduler-ember).\n- Install build dependencies with `npm install`. Dependencies are stored in `package.json`. (If you have not installed phantomjs, you will need to install it globally: `npm install --global phantomjs-prebuilt`.)\n- Commit your changes.\n- Run the development server with `ember server`.\n- Open in your browser at [http://localhost:7165/](http://localhost:7165/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterichadbourne%2Funscheduler-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterichadbourne%2Funscheduler-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterichadbourne%2Funscheduler-backend/lists"}