My Rails Porject
This is my third project of Flatiron bootcamp. After two months hard working I gained some understanding of web development. Rails is very similar to Sinatra only more integrated and effective. In Sinatra if we want to implement some features we may have to add some gems, with Rails some of them are already included. Let’s dive in!
Coming up with an idea
The gist of using these frameworks to develop a website is the same, what’s different is how you want to relate the associations between models in order for them to implement the fuctionality that you wish users would see and interact with.
At first I wanted to make a user-team-player project which is very similar to a fantasy league. User has many players through team and vice versa, however in this way team will be the join table which makes team belongs to a player. I think it very odd so I decided to make one more logical to me. Then I came up with this user-trip-flight management system because I was doing some research of going back to China to visit my family and friends.
Models, attributes, associations and validations
Apparently this project will have a user model, a trip model and a flight model. User has many flights through trips and flight has many users through trips too. Solid as a rock.
For user I want it to have standard attributes as username, email, and since we’ll be using bcrypt to safely store the password, we’ll use password_digest instead of plain password. Bcrypt will automatically validate the presence of password_digest we can just ignore that. I want username and email to be unique and present so I add these validations.
For flight I want it to have a unique flight number, departure airport code(like JFK), arrival airport code, departure and arrival time, flight duration and price. And all of them should be present. I added from city and to city attributes for region search functionality, just like when you put in New York it would show flights departing from EWR, JFK and LGA.
Trip is the join model for user and flight, the requirements specify that we must have submittable attributes other than user_id and flight_id. That’s easy, we just have to mirror the real world booking process into our project. User needs to submit traveler information when booking a flight.
Controllers actions, routes and view pages
After setting up the models, we need to design our controller and routes flow. I want a home page, all user page and flight page to be independant. And I also want my trip pages to be nested under other routes. Just like the real life, you would only want to book a trip after confirm the flight you’d like to take. So trip’s new and create actions will be nested under fligths. When you check your trip, it’s more likely to be a property of a user, which makes other trip pages nested within users.
Besides all these we’ll still need a session controller and corresponding actions and routes to handle sign in and log out request.(Sign up has been defined by users/new)
Authentication module and third party login service
This is a very handy feature that you could easily implement by just adding omniauth, omniauth-specific-third party-service and dotenv-rails gems to your gemfile.In my case I used facebook which makes omniauth-specific-third party-service omniauth-facebook. What we need to do next to set up this login service is to go to the service and set up project key and secret, and add it in a .env file in the root directory of your project. Be sure to protect it by adding it to .gitignore, otherwise everyone could have the access. Last we need to create a omniauth.rb in our config/initializers with the code below
At this point the set up is completed. But where is it going to take me after the facebook intercept and redirect? So we need to set up a standard callback route for it
get ‘/auth/facebook/callback’, to: ‘sessions#create_with_fb’
Be sure to check the version of your omniauth gem. I’ve been stuck for almost two hours just because wrong version gem told me it couldn’t find the callback route.
From here it’s just what we do all month. Create a new object for form builder in that page to handle the form parameters and authenticity token. Use strong params to protect from forging form information and redirect to corresponding page if the object can be sucessfully saved, otherwise we need to handle errors and tell the user which part of the form they didn’t fill up right. For show and index page we need to be aware of what kind of data we’re rendering to the viewer, so we’d better prepare the right instance variables beforehand.
After spending some time working on our actions, we’ll definately find out many of our code is repetitive. This is where our helper method comes in. For my project I defined a #current_user, a #home_page_if_logged_in and a #require_logged_in to abstract same code that limits actions. Also I have set up #set_obj or #set_obj_and_others to reduce same code repetition by using a before_action helper method.
Partial and Layout
If helper method is a way to mainly abstract code in model and controller, then partial is our powerful tool to DRY views up. Usually if the more beautiful a view page is, the more complicated html structure it has. Trust me, you wouldn’t want to write that code twice. Even if you could bear the process of writing twice, what if you need to change them even a slight bit? Usually form partial is very handy because new form and edit form are quite similar. Other than that, making a partial for recurring snippet is also a good idea.
It’s always stressful and fun to start a project from nothing. Thank you for reading. See you next time!