My Flatiron School Rails App
Tags: flatiron, rails, flatironschool, ruby
Published: 2020-07-21 02:33:31

# [project code](https://github.com/colerau/appt_booker)  •  [project demonstration](https://www.youtube.com/watch?v=p2O7vWri394) 

# Overview

I have created a web app that books appointments for the Parvenu hair salon. To book an appointment, a user chooses a stylist (employee) and an appointment time. If the appointment details pass validations, the user can then edit or delete their appointment. The URL to see which user has the most appointments is `http://localhost:3000/users/most_appointments`. 

The app was built with Ruby on Rails. A user can sign up and log in via Facebook so they don’t have to remember a new password. [OmniAuth](https://github.com/omniauth/omniauth) was used to create this feature. My application follows REST, MVC, and persists data with a SQLite database. 

# Model Associations

* A User has many Appointments
* A User has many Employees through Appointments
* An Appointment belongs to a User
* An Appointment belongs to an Employee
* An Employee has many Appointments
* An Employee has many Users through Appointments

The consequence of these associations are that Users and Employees have a many-to-many relationship, the join table being Appointments. 

# Model Attributes

**User:** 
* id 
* name
* email
* password_digest
* password_confirmation
* uid (user_id for Facebook)
* image (user's Facebook profile picture)


**Appointment:**
* id
* user_id 
* employee_id
* time


**Employee:**
* id
* name

# Project Process 

The hardest part of making this project was figuring out how a user would choose an appointment time.

I first thought of creating another model called EmployeeTimes, which would belong to an Employee (an Employee would have many EmployeeTimes). However, if I chose this solution, I wouldn’t have known how to make the `appointments#new` form. I would have needed to alter what the form displays based on which employee the user chose. It seemed like I needed to know some JavaScript in order to make this functionality. 

Ultimately, I decided on incorporating time as an attribute of the Appointment model. Time would be a DateTime data type. Before the appointment's time would be saved to the database, a number of validations would be performed, such as: is the time between 9:00am and 5:00pm? (to coincide with salon hours); is the time’s hour an odd number and the time’s minute zero? (to make sure appointments are spaced at least two hours apart); and, is the time unique and in the future?

As an aside, I was lucky to find out that Rails handles mass assignment with DateTime very well, so it was easy to create/edit an appointment with the `params` hash. 

---

I’ve heard of software developers fearing time zones, and I got a taste of that with this project. After some googling, I figured out I needed to put the time zone I wanted (GMT-7) into config/application.rb with the line `config.time_zone = "Pacific Time (US & Canada)"`. This would prevent the appointment time from being off by seven hours. 

One thing I feared implementing in this project were nested routes, but they turned out to be my best friend. Nesting my appointment's resources under `users` gave me routes like `/users/:id/appointments/:id/edit`, which let me easily use Rails `_path` helper methods. I figured out that the `_path` methods can accept two ids, the first argument being the user’s id, and the second argument being the appointment’s id. 

Rails' `form_for` made CRUD a blast to implement. `form_for` knew implicitly whether a user was editing or creating a new appointment. Rails was definitely a welcome change from Sinatra, though the convention over configuration philosophy was frustrating at times if I didn’t know the exact Rails convention.