It’s Rail Good! Food For Fido
I think you meant real?
Nope! I meant Rails. More specifically, Ruby on Rails.
Do you remember our good old friend Sinatra ? Well, Rails is basically Sinatra but better! It is a web application framework that has everything you need to create an application utilizing a Model-View-Controller design. I say that it’s Sinatra but better because unlike Sinatra, Rails has a lot more “magic” and requires less repetition when dealing with routes and controller actions. This allows you to DRY up a lot of your code (because we programmers are lazy and like efficiency).
So let’s get into my rails project!
Minimum Viable Project Requirements
- Use Ruby on Rails framework to build app
- Model must include the following associations: A
has_many :through. This will be your many-to-many relationship.
- The join table must have user-submit table attribute
- Must include appropriate validations to protect against bad data
- Must include at least one ActiveRecord scope method. This scope method must be chain-able with an ActiveRecord Query method.
- Must have standard user authentication
- Authentication system must allow the option to login from a different provider (e.g. Facebook, Google, Github)
- Must include nested routes for new and index
- Forms should appropriately display validation errors
- Application must be relatively DRY
- DO NOT use scaffold to build project
Okay to be completely honest, trying to find ideas for this project took me longer than I expected. It wasn’t even the topic; it was more so piecing together associations for the models I wanted to use. Out of the two weeks given for project week, I spent a whopping 1 week figuring out what topic I wanted to do and how I would build the associations. I think I laid out about 3–4 different ideas and considered over 10 models to associate. Things were definitely getting out of hand. I had 6 models and super complex associations that I understood but didn’t really know how to associate properly. So I started panicking because well, if I didn’t know how to associate my models properly, then my whole project would basically be broken. The basis of the project was to work with multiple models through associations. As the week went by, I got more and more anxious about my project. The horror story of building out a “completed” project only to find out your associations were actually wrong ridden me with so much anxiety.
The beginning of the second week rolls around and I touch base with my amazing cohort lead. She takes a look at my schema and tells me that I can actually condense my models so that my associations can be a lot more simple. This gave me so much hope for the future of this project because at that point, I really wasn’t sure if I was going to make it.
So after MUCH deliberation, I finally came up with the project ‘Food For Fido’. This web application allows fellow dog owners or enthusiasts to find fresh food recipes for their pup! The user can create an account to rate and comment on recipes. So let’s break down this project.
Starting Up Rails
To start up rails I needed to go into my terminal and run the following:
rails new ‘food-for-fido’
Once in the project, I ran
I will eventually run bundle install a couple more times after adding a couple more gems but we’ll get to that later.
Models and Associations
First order of business, we have to figure out what models we want to use and then how to associate them with each other. This was honestly probably the hardest thing about this project. This task sounds so simple but depending on what functionality you want your application to have, is how differently you need to associate your models. This whole process of associating your models was so painful for me. It went from the most simple association to the most complex crazy association that even a seasoned developer would have a hard time wrapping their head around. I was thinking of every possibly association that these models could have with each other and ended up throwing away so many ideas because it just got too much for me. Eventually after ensuring that whole week of being lost in the abyss, I finally was able to create my models and associations:
After this, everything else seemed like it came together pretty quickly thanks to our lovely generators!
Okay so going back to what I was previously saying about why Rails is similar to Sinatra but better: generators, generators, generators! So you know how in Sinatra we needed to create all of our tables, controller files and view files by hand? Well, Rails can help with that! Rails comes with generators that can build something as simple as creating a migration to creating your entire project using scaffolding (but this is not good practice as tempting as it sounds because well first it’s technically cheating but also there are so many unnecessary files it creates that you have to delete). For my project I used a resource generator and ran this in my terminal:
rails g resource User name:string email:string password_digest:string
This created the controller, view, helper, migration files, and routes but did not create any code for the files other than the routes. The resource generator basically gives you an outline of the things that you need to build out a project and you write the code you need inside those files. It is more customizable and less prone to unnecessary files and errors. One of the very amazing things that Rails has to offer! I was actually so surprised how fast this built the outline of my project. All I needed to do now was to create the most important part, the code!
Validations are one of the most important parts of your code. It protects against bad data given by the user. ActiveRecord comes with methods to help validate your attributes so you don’t have to deal with troll users and don’t have to implement so much code to combat it. How fantastic is that! We are all familiar now with our lovely
has_secure_password that’s used in conjunction with the gem
bcrypt . This protects a user’s password from any of those hackers by salting and hashing it. ActiveRecord also has validations for presence, uniqueness, as well as range of number which is what I used in my project. There was no real right or wrong way to use validations it all depends on how protected you want your web application to be. As for my I attempted to use the
confirmation validation but it ended up being a bit too complicated when I implemented Omniauth. Another great thing thing about validations is that when you fail a validation, you get an array of errors. These errors are extremely helpful to not only the user, but for you as well. When something is not allowing you to get to your next page, that is something that a developer needs to be aware of in order to store good data. It also helps with user experience because we want our user to know why they were not granted access to whatever page. Flash messages were also something I implemented in my code when I needed to redirect a user.
Okay you’ve definitely seen this before. When you go, medium, it prompts you to login with different providers. That was one of the requirements for this project and to be honest, when I did the lab for this I was so confused. First, I started with trying implement omniauth using Facebook and followed along with some documentation and the learn readme. I kept getting an error that there was no route for POST so I had to make some adjustments to the route. I finally got it working BUT, I failed to realize one thing that really stopped me from using Facebook. It utilized an https not an http. It was so frustrating because I spent almost an hour trying to figure out how to fix the route. Anyways so I decided to use google instead. After reading some documentation, a blog by Jenn Hansen, and a lovely video by my instructor, I was able to finally implement this correctly. There are definitely a lot of tedious steps when implementing this feature into your code but it really is worth it. To not have to actually type in login information and automatically sign into my application was amazing. If you want to implement omniauth using google, then definitely give Jenn’s blog a read! You can also read documentation here on omniauth.
CRUD and Routes
Remember our friend from Sinatra, Create Read Update Delete? Well, it doesn’t leave our side! This is still the convention to follow to build out your web applications with Rails. I really went back to this every time I caught myself wondering what my next step would be to build out my application. Especially with our many-to-many associations, it’s definitely something you want to keep in mind when building out your application. Rails even comes with resources which allows you to define all of your RESTful routes in just one line of code! However, it’s definitely not something that you’ll just drop and use carelessly. You have to be careful with what controller actions you actually want to use it for. Say, if you actually need to alias the route so the URL matches what you want to display to the user but it’s pointing to a different action name defined in the controller. So when I was building out my project, I just stated out with resources for all of my tables but I ended up customizing it to match a ‘/login’ or ‘/logout’ URL. I even made some custom routes to add a link to filter the recipes by cook time, name, and recently created. You also have to be mindful of the order in which you create your routes. You don’t want your user show page to be running before you even create a new user! So with all of these helpful features that Rails provides, it also comes with greater responsibility.
Since we are dealing with associations, especially a many-to-many relationship, we also needed to create nested routes. Since we have two parents and a child, nested route allow us to display this relationship in the routes as such:
By creating a nested route, this also created more path helpers to use to
link_to our show page for the child.
Dealing with these many to many relationships you can only imagine the amount of code I needed to create for this project, not to mention repeating code. To DRY up my controllers and views, I created helpers and partials.
Oh how grateful I am for these. First let’s talk about partials. Basically partials allow you to render code into your view files and are specifically named with a “_” at the beginning so that rails knows it’s a partial. This allows you to utilize the code in the partial in another view. This was particularly helpful when I was creating my forms for new and create.
The daily life of a developer and a software engineering student. I think out of all of my projects, I had to debug the most with this project. There were so many moving parts that I didn’t think I would be able to make a viable project. To help with debugging, I used
pry and required this in my
gemfile and environment. I know there was
byebug that already came with rails but I felt most comfortable with
pry. I think eventually I will learn how to use other debugging tools but trusty old
pry got me through this project so thank you
Coming into this project I assumed that it would require the same skill level that all the other projects did but just a little more. I was so wrong. This was the hardest project thus far that I’ve had to build. I think more so it was because of the fact that Rails really tests everything you’ve learned thus far from simple logic to refactoring to a complex association. This was definitely a big milestone for me and I’m so grateful for Flatiron for constantly challenging me to be a better developer than I was a couple months ago. For this project specifically, in the future I would love to implement features to have users request to create recipes and interact with one another and send each other messages. However, this is definitely a stretch goal. I will say that styling wise, it wasn’t any better than my previous project but I’m hoping to implement better user experience in the future. Now, it’s time for me to prepare for my assessment!