Sign in

Handling a Has Many, Through: Relationship in the Front and Backend

When I started the software engineering program at Flatiron School, I knew just about nothing in regards to programming. I may have heard “JavaScript” tossed around occasionally, but Ruby? React? Those terms were nowhere to be found within my vocabulary. Through my time at Flatiron, though, I was able to learn foundational programming in both JavaScript and Ruby, and with that knowledge, I’ve built a few small and light web applications with React and Rails frameworks to help cement it. Now that the program is coming to a close, I have all the fundamentals I need to aid in my pursuit of a full-stack developing career.

In each module of our program, we’re asked to complete a small project put together with capabilities learned thus far. Being that this is the last module, I was tasked with creating a small web app with a React frontend and Rails backend. Now, I could talk you through my entire project process, but that would be, well, boring. And quite a long read. Instead, something more helpful I could talk about would be what I believed to be the most challenging aspects of this build.

To be specific, the small app I built is a very light version of an itinerary/trip planner. For this, in my backend, I have a User model so a user can login and view their saved trips, a Trip model, and another model I called Category, which would allow a user to create their own trips under an umbrella category. For example, a user can create a trip under the category “Europe” or “European” but they may be going to just Spain and France for one specific trip, and maybe in the future they’ll take another trip to Europe but only go to Italy. I am of course still very much a beginner programmer, so this was my first time building a backend where the database included a joins table (the trips). This just means my user model can have many categories through their trips and vice versa, and trips will belong to a user and also a category. Rails and Active Record make creating these associations so simple (one line of code in the respective model that says something like “has_many :users, through: :trips”). Going in, even though it seems straightforward, I did not immediately realize that a user could not be associated with a category without a trip to go with it. My trouble with this was first in the frontend trying to elegantly let a user see the entire list of all categories and then giving them to a trip they create, thus granting a user with their own separate list of categories. Then, handling all that data in backend and making sure everything gets associated correctly while still authorizing and validating the data.

Listen, maybe this doesn’t seem too complicated, especially written out straightforward like this — but like I said, I’m a beginner and this was tough! By far this was the most challenging aspect of the entire project, so let’s go through how I solved this issue.

First, after all my models were fleshed out with associations and small validations, I had to think about what this should look like. I knew I wanted a form to create a new trip, so the natural conclusion here is to add a feature where a user can first create/select a category, and that way I would be able to associate that data with a new trip. In the frontend, this category form would need two inputs, but only one of which would be necessary. The first one would be a simple text input where, if a user wished to create an entirely new category, they could type that in. The other component would be a select/drop down menu, where a user could look through all of the categories in the database and select one, should their desired category already exist. To aid in this capability I would need to do some work in the backend, namely creating a new route to map to a method in my categories controller, where, when a request was sent, it would simply return every category. Then, when that data is returned after a get request, I could map through every instance and create an option tag for each category to go into the select form. Easier said than done, it ends up looking something like this in my aptly named “Trip Form” container:

After a user enters or selects a category, I need to again send a request to my backend, this time a post request where I can hit my create method in my categories controller. There, I can create or find a category. Easy enough. Like I said earlier, I wanted this entire creation process to be at least somewhat elegant/seamless, so after a category is chosen I immediately had a new form toggled where I had the first category form disappear and a new one for a trip would take its place, with the category already named. Having this selected category’s data allowed me to then behind the scenes give the new trip it’s ID to be my trip object’s category_id. Viola! Now they’re associated and I can with that entirety of data create new trip for my user, and only associate certain categories for them to view and edit. Hopefully this isn’t confusing, and here are some more snippets to help visualize:

My post request, ended with a reroute back to the user’s category view page after a submit.
My create methods in my categories and trips controller, respectively.

All in all, I would say this looks pretty simple, and maybe it is. Before I came to this conclusion, there were a couple different iterations that were either way too sloppy or, to a user, would make zero sense. Finally, after creating a Frankenstein’s monster of an app, I had to take a large step back and reorient myself to what exactly I wanted this to be. That step back was greatly beneficial. I was able to create a firm vision for how I wanted this app to look, and logically find the solution to any problem I encountered using that vision. In this case, ‘simple’ is a huge compliment, because that’s all it needed to be.