Rails Portfolio Project

For my Ruby on Rails portfolio project, I decided to do something using an additional API, as it had been fun to learn how to use Facebook’s OAuth one during the lessons.

As I have for my previous projects, I decided to incorporate one of my passions/hobbies: the New York City Subway system (actually, it uses all transit options in the city).


At first, I thought I would use the MTA’s set of APIs. However, I quickly realized that that would not allow me to provide transit directions (how to get from point A to point B) in the way that I wanted, as—duh!—they only provide real-time status of trains, buses, etc.

As it turns out, Google uses information gleaned from MTA’s API, which is formatted according to Google’s GTFS specification, and uses their computing power to figure out the directions. Ok, so I’m going to use Google Maps’ Directions API. I found a nice Gem that does that—all I had to do was provide my API key.


Next, I had to begin thinking about what models I would use. Obviously, I’d need a User model:


  • Fields
    • First name
    • Last name
    • Email address
    • Password
  • Validations
    • Presence of, uniqueness of, and email-address-ness of Email address
    • has_secure_password

and an Address model:


  • Fields
    • Line 1
    • Line 2
    • City
    • Borough
    • ZIP code
  • Validations
    • Presence of Line 1
    • Presence of Borough, and its inclusion in [‘Bronx’, ‘Brooklyn’, ‘Manhattan’, ‘Staten Island’, ‘Queens’]

Since I am building this app only for New York City, I didn’t need a State field. And I included Borough so users could filter addresses, a requirement for the project.

As for the has_many through requirement, it made sense to create a Route join table. A Route would belong to an Origin and a Destination (both Addresses), and a User. A User has_many Routes, and Addresses through Routes; an Address has_many Routes, and many Users through Routes.


  • Fields
    • Name
  • Validations
    • Presence of Origin and Destination
    • Presence of Name, and its uniqueness at the User level

The Name field will be a user-supplied label for the Route.


The controllers are very similar to what we’ve seen before. In addition to all seven RESTful routes for each of the models listed above, I built a Sessions controller to deal with login and logout logic. I wanted user to be able to login using either email/password combination OR OAuth2 through Google, so there are both “sessions#create” and “sessions#create_with_google” routes. A Sessions helper defines helper methods that interact with the session hash.


Got to use a lot of partial views, which was fun. There are lots of different ways to display or list addresses. Of course, put the forms into partials. In addition, I moved the error-message-displaying stuff, included on each form, into it’s own partial in /app/views/shared.

The “routes#show” route is where the Google Directions API does its stuff. The array returned by the google_maps_service gem looks pretty complicated at first glance—it’s an array of hashes many levels deep—but once you get the hang of it, it’s actually pretty simple. Here’s an example of where the Subway stop at which to get off is stored:

          :html_instructions=>"Subway towards Wakefield - 241 St"
          :transit_details =>{
            :arrival_stop =>{
              :name=>"3 Av - 149 St"


Video walkthrough