Building a Rails CMS

It’s Rails assessment time! I’m chugging along at the Flatiron School Learn Verified program, and just completed the Rails section. For this section’s final project, I was tasked to a build a content management system with a couple of interesting requirements (complex associations, nested forms, data validations, Omniauth…). I decided to make a Homebrewer app for tracking your homebrewed meads, beers, and wines.

Has Many Through & Nested Forms

The most challenging part involved building a has-many-through relationship and making a super nested form to assign data all at once. My Brew model has many ingredients, and an ingredient can have many brews. They are related through a recipes join table, which additionally stores information about the quantity of the ingredient used in a brew.

I wanted a user to be able to add a new brew with all of its ingredients plus the quantities of each ingredient all at once, in a single form, with the Quantity and Ingredient Name fields displayed in the proper places. I ended up needing to make sure that the Brew model accepts_nested_attributes_for :recipes, and Recipe accepts_nested_attributes_for :ingredient (note the singular, not plural, ingredient). Then I made a Brew form using the form_for helper. Inside of this went a fields_for :recipes helper, containing the Quantity field, and nested inside that, a fields_for :ingredient helper with the ingredient Name field. In order to create canonical instances of ingredients (instead of creating, say, a new database entry every time a user enters Honey as an ingredient), I made a custom ingredient_attributes method in my Recipe model which will find the ingredient if it already exists, or a create a new one if it doesn’t.

I found these sources particular helpful in my quest to make this super-nested form:

Stack Overflow: Has Many Through Nested Forms

Stack Overflow: How to Edit Attributes of Join Model in Nested Forms

Nested Resources

Users have the ability to add notes to each of their brews. Since I never want notes to be accessible outside of the context of the brews they belong to, I nested notes under brews in routes.rb.

However, the form_for helper automatically expects simpler non-nested note routes. In order to keep using the form_for magic, and as suggested by a few Stack Overflow sources, I decided I would also declare non-nested :notes resources.

Omniauth

Initially I wanted to try allowing users to sign in via Google. In the lessons so far I’ve only practiced hooking up Facebook with Omniauth. Unfortunately I ran into an issue with OpenSSL and security certificates – which some tutorials actually warned me about – and attempting to fix the issue led me down a rabbit hole far beyond my current skill level. Instead I ended up sticking with a Facebook login.

An interesting note: be sure to set a limit: 8 on the :uid integer column in the users migration to ensure a bigint! Facebook’s UIDs are not small.

Written on April 25, 2016