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
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 was used to create this feature. My application follows REST, MVC, and persists data with a SQLite database.
- 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.
- uid (user_id for Facebook)
- image (user's Facebook profile picture)
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
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
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.
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.