Building a Rails app using TDD, Devise, Omniauth, and Nested forms

Karuna Sehgal
Karuna Sehgal
Published in
7 min readOct 25, 2016

For the third assessment project at the Flatiron Learn Verified Online Program, I was required to build a Rails (Model View Controller) Application. This also involved using Authentication gems like Devise and Omniauth. Last but not least I also planned on using TDD (Test Driven Development) for Rails project and deploying it on Heroku. It sounds like I am being too ambitious here but then I thought why not..worse case scenario it will be a great learning experience.

Below is a walkthrough of my Rails app:

Food Travels Rails App Walkthrough

In it I demonstrate:

  • New user signup.
  • Creating, editing, and deleting a food travel story.
  • Logging out.
  • Logging in as another user.
  • Trying to view, edit and delete someone else’s food travel story.

Conceptualization

One of my favorite hobbies includes trying different kinds of international cuisines. I learn about them from friends, family, food blogs and exploring diverse neighborhoods though out the world. So I decided to create a Rails app where a user can create food travel stories and share them with other users.

How it works:

Users create accounts and are provided full CRUD capabilities (Create, Read, Update, Destroy) in creating food travel stories. Users can only edit and delete their own stories. Users can also comment on each other’s stories.

Controllers: I have a user, food, destination (similar to a post), comment and application controller. The user, food, destination, and comment controllers inherit from the application controller.

Models: I decided to have a user, food, destination and comment model. The user has many destinations and comments. The user also has many foods through destinations. The food has many destinations and has many users through destinations. The destination belongs to user and food. The destination also has many comments. Last but not least the comment belongs to user and destination.

Views: I knew that I would have an initial landing page, where a user would go when the user is not logged in. I also created a layout template with messages and navigations partials, to avoid copying over basic HTML on every erb file. There would have to be views for destinations - viewing, creating, editing and a form partial as well. And for users, a sign up page and a login page via devise was crucial as well a show view too.

Implementing TDD in Rails App

Through out the lessons and labs at Learn.co, we have to pass tests in order to move on in the curriculum. Tests guide us and help us further comprehend the core concepts in Ruby, Sinatra, and Rails. I thought that by writing tests will not only be a challenge for me but will also help me improve my confidence of writing and understanding code more effectively.

For the Food Travels Rails App, I focused on only writing model specs. It was a slow process for me since I was learning about writing tests as I went. Every Day Rails Testing with Rspec was an amazing resource that made the process more easier. Looking at prior Learn.co lessons and labs was a tremendous help for me as well.

At times I wanted to forget about TDD and finish the app as quickly as possible. However, I knew with writing tests my app would be worth it in the long run and it is incredibly gratifying when a test prevents the app from crashing. All great skills become better with practice so the more I use TDD, the more I will understand what I need to test and how to write those tests.

Authentication using Devise and Facebook Omniauth

Being that Devise and Omniauth occurred at the end of Rails curriculum, these topics were fresh in my mind. Yes both these topics can be challenging but what helped along the process was the Devise documentation. Following the Readme step by step help me implement Devise successfully in my app.

I wanted to add a name attribute to my Devise registration view when a user signs up for an account. This requires parameter sanitization (protecting your data). Before I started working on Food Travels, I worked on a side project with a couple of Learn students, where we built a blog app using Devise and added a new attribute. That project helped me succeed in adding a name attribute in the views, configuring parameter sanitization and permitting additional parameters in the Application Controller using a simple before filter.

One of the requirements for my project included giving the users an option to sign up with something like Facebook, Twitter, etc. I went with Facebook as it made the most sense with Food Travels. By following the procedure of setting up Omniauth from previous Learn lessons I was able to implement it successfully in my app. One of the steps included adding the following method shown below in the User model, where I look for a user with the Facebook as the provider and the user’s uid (uid means unique identifier), pair and create them if they aren’t in the database.

Nested Form with a Belongs_to Association

Within my Destination form view, I wanted to add the name and type of the food attributes. Being that Destination belongs to food and user, I had to keep in mind that I need a nested form with a belongs_to association. None of Learn lessons and labs covered this topic. Despite consulting with several students in the Learn community, doing Google searches and checking out Stack Overflow, I couldn’t find any concrete examples of a nested form with a belongs_to association.

However, Learn provided their students a link to previously recorded videos and I found one in which one of the instructors created a nested form with a belongs to association. After checking out the video I realize that creating a nested with a belongs to associations is not an impossible task. I followed along the video to build out the basic framework and it was useful to see the thought process.

First step involved writing a custom writer method in the Destination model where we’re only creating a new food if it doesn’t already exist with the current name:

Next I had to add a text field to enter the name and category of a new food. The value of the name would be nested under my destinations_params, so I didn’t have to add too much code to my controller. I used the fields_for helper to do this very easily.

The fields_for helper takes two arguments: the associated model that we're creating and an object to wrap around. In this case, we've passed in the food association and built an empty food associated with the destination.

Within in the Destinations Controller, I had to update the strong params so that way the params hash will now have a key of :food_attributes nested under the key of destination.

Destination_params in Destinations_controller.rb

Also I had to update the new and show action within Destinations Controller, so that way the controller recognizes that Destination belongs to food. In the new action, the build_association method returns a new object of the associated type (@destination.build_food). In the show action, the association method returns the associated object (@food = @destination.food).

Heroku

Unfortunately learning how to deploy an app through Heroku wasn’t covered in Learn.co. So I googled to learn about the process of deploying an app and I came across Michael Hartl’s Ruby on Rails Tutorial, which was a valuable resource for me. I followed this tutorial one step at a time, first by creating the sample app that was covered in the tutorial and then I followed the same process with Food Travels as well. Overall it was a straightforward process. In my Gemfile, I placed Sqlite3 in the testing mode and Postgresql in the production mode since Heroku does not support sqlite3 in production mode.

Other Features I Used

Because of the Bootstrap-Sass gem and the Sass-Rails gem, I was able to successfully implement Bootstrap and Sass into my Rails app. The design process was quite seamless. I didn’t have to worry about adding any CSS. My main focus was to concentrate on the functionality of the application and not on design. Bootstrap and Sass helped me maintain that focus.

Overall, building Food Travels was an amazing learning experience. Portfolio projects such as this one are great when it comes to combining all the things I have learned thus far in the curriculum and putting it together. I have become more comfortable with building a Rails app from scratch and am now looking forward to implement some jQuery to Food Travels in order to make more dynamic in the near future.

Food Travels is live on Heroku. Check out the rest of my code here.

Thank you for reading this blog post.

Learn Love Code

--

--

Karuna Sehgal
Karuna Sehgal

Woman on a mission - to live the best life possible!!