How to build a trip management system using Ruby on Rails

Before it gets started

Figooooo
6 min readApr 4, 2021

This is my third project at Flatiron Bootcamp. After two months of 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 functionality 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 on 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 users I want it to have standard attributes like username, email, and since we’ll be using bcrypt to safely store the password, we’ll use password_digest instead of a 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 the 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. The 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 pages, and flight page to be independent. And I also want my trip pages to be nested under other routes. Just like in the real-life, you would only want to book a trip after confirming the flight you’d like to take. So trip’s new and created actions will be nested under flights. 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 requests.(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 the 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 access. Last we need to create a omniauth.rb in our config/initializers with the code below

At this point, the setup 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 the wrong version gem told me it couldn’t find the callback route.

RESTful routes

From here it’s just what we do all month. Create a new object for the form builder on that page to handle the form parameters and authenticity token. Use strong params to protect from forging form information and redirect to the corresponding page if the object can be successfully saved, otherwise we need to handle errors and tell the user which part of the form they didn’t fill up correctly. For the 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.

Helper method

After spending some time working on our actions, we’ll definitely 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 the same code repetition by using a before_action helper method.

Partial and Layout

My partials are almost as many as my view pages.

If the 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 the 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 the new form and edit form are quite similar. Other than that, making a partial for recurring snippet is also a good idea.

Last

It’s always stressful and fun to start a project from nothing. Thank you for reading. See you next time!

--

--