It's December 2020 and Los Angeles has just been issued our second 'Stay At Home' order. So when I was tasked with building a Rails-based web application for Flatiron School's third module project, I knew immediately that I wanted to create something that would allow me to fantasize about once again getting out of the house. After months of quarantining and dreaming about one day vacationing again, I decided to create a web application for users to be able to manage their vacation homes.
The project had a number of specific requirements. The first of which was that I had to have at least two
has_many, through: relationships. I decided to initially create three models for my project. I knew that I would have a user model and that each user would
has_many :properties and
has_many :locations, through: :properties. That in turn would make my
has_many :properties and
has_many :users, through: :properties. These relationships made my
Property model serve as my joins table, uniting my
Location models. I knew my property would have user-submittable attributes for bedrooms and bathrooms, but what fun is a vacation property if it doesn't have amenities?! Enter my
Naturally, a vacation property
has_many :amenities but an amenity also
has_many :properties. I couldn't just have an
Amenity model. I needed another joins table to connect my properties and amenities. My new
PropertyAmenity model and respective data table would serve as a more standard joins table, just working to connect those two models.
The other major requirement for this project was to have the capability to have 3rd authentication either through Github, Twitter, Facebook, or Google. I decided to include options for both Github and Google. Thanks to the smarts of my fellow classmate, CJ, I was able to use both platforms to authenticate users in my application. Once I had these first steps set up I started to add functionality to my site.
My main form to create a new property needed to be set up with nested form capability so that a user could create a new location for a property as well as a new amenity if they have one that isn't already listed. To do this, I had to set up my Property model to accept nested attributes for both a location and an amenity.
I included validations to ensure that the names for both a location and amenity could not be blank and then set up my
property_params to permit the nested attributes for each. In addition to permitting these nested attributes, I also had to permit
amenities_ids: if a user were to select amenities that had already been created and
location_id if a user were to select a location that already exists.
Once I had my basic CRUD functionality set up for a user's properties, I wanted to add the ability for someone to add images. I had no idea where to begin but was lucky enough to stumble upon a very helpful Medium article by Ana Harris that walks through a step-by-step guide to adding upload image functionality using Active Storage. I installed active record storage in my terminal and that immediately generate two tables in my database:
Once that was set up, I simply had to add
has_one_attached :avatar to my Property model and set up my property_params to also permit :avatar (which is what I decided to call my image). I added a simple line of code to my view to be able to disply the image if it was uploaded:
<% if p.avatar.attached? %>
<img src="<%= (url_for(p.avatar)) %>" class="card-img-top" alt="...">
<% end %>
Ta-da! Now a user can admire their gorgeous vacation properties in all their visual glory!
Thanks for reading! You can watch a full run-through demo of my app here: https://www.youtube.com/watch?v=v6jWvsM1jN0