For our third project at Flatiron, we were asked to build a fully functioning rails app. My project idea was to create an app to track races people have run. I am an avid runner myself, and I thought it would be handy to have all of your races in one spot. A functionality I added is when a user adds a race to their profile, they can add their finish time and a short review about how they felt about the race. The review feature is useful for other users to see how the race went, what the course was like, and perhaps will sway their decision as to whether or not they’d like to run in the future.
Similar to the Sinatra project, keeping track of active record associations is absolutely crucial. I quickly learned that if you didn’t have the associations set up properly from the get-go, nothing else in the app would work the way you anticipated. That being said, even with the associations set up properly, you had to be cognizant of how you were utilizing the associations.
For this app, there are 3 models: user, race, and user_race. User and race have a many-to-many relationship, with user_race acting as the join table. A requirement of this project was to have at least one user submit-able attribute in the join table, which I decided would be start_time, finish_time, and review.
To create a user_race, I provided a user with two options. First, they could submit via a nested form inside of race#new.
In the above image, there are fields for creating the new race, while simultaneously adding it to a user’s profile as a user_race with their times and review. Additionally, they can add an already existing race to their profile, with their own times and review, via a nested route (i.e. /races/3/user_races/new).
Refactoring was definitely the biggest challenge for me during this project. Gone are the days of getting code to “just work”, now you have to make it work AND do it concisely. The before_action was a useful to keep my controllers thin, however, it can potentially make things confusing while debugging. I found view helpers to be the most frustrating part. Trying to remove ruby logic from the view while keeping a “link_to” method was not as straightforward as I’d hoped.
In the example above, the top box is my original code in the view page, the middle box is the refactored code in the view helper, and the last line is how it was displaying in the browser. After much research and help from other students and my instructor, I found that interpolating the link_to inside the content tag was not the correct approach.
In order to get the link_to to function as a link, I needed to concatenate the string and the link_to by using “concat” inside of a content_tag block. I tried my best to keep as much logic out of my views as possible, but there is still room for improvement. Lastly, partials were a great way to refactor forms and repetitive code being rendered in several different views.
Another requirement of this project was to include at least one scope method. One of the scope methods I added was :most_popular_race for the Race model.
Basically, I wanted to show the race that had the most users. I started by joining the user_races table and grouping it by user_ids, since this is how the join table keeps track of which users have run which races. I then ordered the queries in descending order by how many user_ids a race had. The limit(1) grabbed the top row with the most user_ids associated to a race. I added a similar scope method in the users class to show which user has run the most races. It’s the same code as the scope method above, except it’s in the User class.
Additionally, I added search functionality to both the users and races index page like so:
This is basically saying if there is a query typed in and searched, the races index page will display the race(s) that contain whatever was typed into the text_field of the search form. If there is no query, i.e. nothing written in the text_field, it will render all races.
Overall, I found this project to be the most challenging, however completing it has been the most rewarding out of all the projects I’ve done at Flatiron thus far. If you would like to learn more about this project, here is the github link and a short demo video.