Off The Rails!
I must admit Phase 3 of Flatiron School’s coding bootcamp was harder than I expected. This time, I found myself having to build a Rails app and having to implement Omniauth in order to allow users to log in with an outside source, it being Google, GitHub, etc. This was tricky but building something that allows a user to log in with Google was quite exciting, as it is something I have seen sites implement frequently.
I decided to create a platform where users can select from a list of languages and share why they would like to learn that language, their goals, the amount of time they have spent on it so they can look at it and stay on track.It’s main purpose is to document a person’s learning journey with a certain language and also to hold oneself accountable.
In order to do this, I used the Rails generator “Generate Resource” to created initial migrations and models for “users, user_languages, and languages.” Users will have many user_languages and will have many languages through user_languages. Similarly, languages will have many user_languages and many users through user_languages. After setting this up, I wrote out the routes and the basic structure for the views.
After implementing log in with the ‘bcrypt’ gem and adding the “has_secure_password” method to our User model, building out the controllers was pretty straight forward and similar to how one would do while completing a Sinatra project. However , implementing authorizations with the helper methods “current__user” and “logged_in?” I struggled to get it to work. I checked to see if the current_user’s id was the same as whatever user_language’s user id(user_languages belongs to a user), then the form to create/edit would render. However I kept getting redirected, which was not supposed to happen. After much debugging I realized that the issue was due to a difference between the datatypes. I realized current_user.id was an integer and the params[:user_id] I was checking was a string. In order to get the correct datatype, converted it to an integer via the “to_i” method.
Implementing Omniauth was not necessarily hard, but it is rather complex. Omniauth can be used with various different providers, but I decided to use Google since a vast majority of major sites allow their users to sign up using their Google account.
In our Gemfile, we must add the following gems:
gem ‘omniauth’
gem ‘omniauth-rails_csrf_protection’
gem ‘omniauth-google-oauth2’
gem ‘dotenv-rails’
First I had to create a new migration to add uid and provider column to my users table. I also had to go to Google for Developers website and create a new project. Afterwards, we go to the credentials tab and add credentials. Here we name our web application the same as our Rails and input http://localhost:3000/auth/google_oauth2/callback as the uri. Google will then give us the necessary credentials.
At the top level of our directory, we will Add an .env file which is where we will set the google_client_id and google_client_secret(in this case). We must then add .env to the gitignore file. In our config/initializer folder we must add a omniauth.rb file where we will add this middleware. The ENV variables are available to us because of the dotenv-rails gem we had previously installed.
In our User model, we add the following class method. This allows us to either create or find a user with attributes from a google account.
In our Sessions controller we must add the following:
Here we are finding or creating a user with our create_from_omniauth method and simultaneously logging us in.
In the homepage, and in the login page, there is a button that allows the user to log in with google. It will redirect you to log in with google.
Last, I did some basic styling with css. I added a style.css file to the ‘app/assets/stylesheets’ folder and then added the following code to the application layout:
I’ll be honest, after being spoiled by Sinatra coming with a basic CSS stylesheet, this was a tiny bit intimidating at first, but after researching and reading https://medium.com/@rv.results/beginners-guide-to-css-styling-on-a-new-rails-application-267070820ba7 it was fairly easy to implement!
I used the platform Canva to create a logo for the app. Styling might change a bit.