The last few weeks I have been chronicling my experience creating an application using Rails and React with the
react-rails gem. One of the more general parts of an application that is applicable to a wide variety of projects is a user login. While building out the skeleton of a user login system for the trivia app I am currently working on, I thought it might be an opportunity to share my approach for others that might be looking to build out a similar system.
Small note about this post: there are so many different ways one could approach building a login system for their applications. If you would like to follow along and build your own, feel free to play around with things and make them your own. To keep things as simple as possible, the system I will be building out here will be pretty bare bones. For this post, I am also working with Rails 6 and not utilizing the React functionality of the application.
Let's Get Started!
The first thing we are going to need is a Rails project to work in. I already have one built, but if you are looking to just play around or create your own new project for whatever reason, you can do so by using the
rails new <app-name> command.
For our login system, the goal is to have a Sign Up page where users can create an account and a Login page that will allow them to log into their account. To be able to test this, we will also have a "profile" page that will be visible after a user is logged in. Let's look at a breakdown of the things we will need to make this happen:
- User Model & Database Migration
The first thing we will need to do is create a Model for our User data. For security, we will be using the
bcrypt gem to salt and hash our user's passwords. To add it, simply go to your gemfile and add
gem 'bcrypt'. Rails may have automatically added this gem when creating a new project, in that case you just have to remove the comment. After making sure it is included in your gemfile, simply run
bundle install to install the gem in your project.
We are ready now to create our actual model. You could just create a new file in the
models folder, but we are going to use a generator for this. The benefit of using the generator is that not only will rails automatically create the model file for us, but it will also create a migration for us so that we can easily create a Users table in our database.
For our user model we will be keeping things simple and requiring just a
username and a
rails g model User username:string password_digest:string
With this command Rails will generate a User model for us as well as a migration for that model. The migration will create a User table with a username and password column as well as standard id and timestamp columns. The reason we are using password_digest here is because of bcrypt. When we connect our model to the gem a little later, this column will give us access to a password and password_confirmation field and allow us to authenticate our user's password.
To use bcrypt with our model is very simple. Let's just go to the
model.rb file and add the helper
has_secure_password inside the class definition. It should look like this:
Now that we have everything connected, the last step is to load our migration. If you haven't already, create your database by using the
rails db:create command. After the database is created we can simply run our migration with the
rails db:migrate command. We should now have a working User model and database table.
We will be taking advantage of the sessions hash that Rails provides for us to keep track of the logged in user. I don't want to go into too much detail here, but essentially this provides us a way to persist the current user through our application so that they don't have to continually log in. Just know that when you see us using
session[:user_id] this is what we are accessing. If you'd like to get a more detailed understanding, feel free to read more about it here.
This next part is optional, but I find it useful when developing my own applications. We are going to set up some helper functions that will allow us to DRY up our code a little bit. Specifically we will be creating a
logged_in? helper that will return true or false based on whether or not there is an active
session[:user_id] and a
current_user helper that will return to us the database model for the currently logged in user. We will place the code for these two in
The last bit we need to set up before getting into the nitty gritty of Controllers and Views is setting up our routes. We are going to have two Controllers we need to create routes for:
users. We will be using the sessions to handle the session actions of logging in and out. The users will be in charge of the actual user data for things like creating and editing new users.
For users we can use the
resources helper and specify the routes we want Rails to make available for us. For the sessions routes, I prefer creating them myself so that I can customize the paths.
The controllers will allow us to perform some logic as well as pass information on to our views. When the user requests a specific endpoint, the controller will execute the corresponding code and make certain variables available to our view for whatever we may need. I prefer to create my controller and view files individually, but you can also use a rails generator to do both automatically. If you are creating your own Controller like I am, just create a new file in the
app/controllers folder using the plural like this:
sessions_controller.rb. The naming convention is important here so that Rails can link your models, views, and controllers together.
For the Sessions controller we will only need a create action. Since our
login route will just render our login view, Rails will automatically handle that for us. In our create action we will search our database for the user entry that matches the username provided in the login form, authenticate using bcrypt and the provided password, and then setting the
session[:user_id] and redirecting the user.
The Users Controller is a little more involved. We will need a new action that will give our view access to a new User instance.
Our create action will be very similar to our login action, with the exception that we will be creating and saving a new user database entry. Lastly we will have a show action that will give us access to the data for the currently logged in user.
We will also be enforcing strong params which you can learn more about here.
The last step is to create some views that we can actually interact with. This is the bit that is most customizable, as you can create whatever variety of UI you would like for this. As mine are also rather basic just to get things working, I will just give an overview of what is needed here.
We will need to first create a
sessions folder within the
app/views folder. There we can create our view files for each of our controllers. Using the naming convention of
<action_name>.html.erb Rails will automatically render the corresponding views to our controller actions. For example, our login view should be
For our sessions, we will need a
login view, and for our users we will need a
For the login and new pages, we will need at minimum a form for the user to input a username and password and submit that data to our controller for handling. Below you can see my bare bones implementation of these pages.
The final show page can really display any information you would like. Here we have access to the data for the logged in user so something like a profile page that displays the user's information, with buttons to edit or delete data might be a good idea.
And that's how I get started with pretty much every Rails project I create to have a bare-bones functional login system. I hope this was helpful in some way if you're still here. Happy Coding!
Oldest comments (5)
Great! Thank for share your knowledge with us.
I tried this and got stuck on "The action 'home' could not be found for SessionsController" it seems like sessions need a home definition but there is not such in the present article.
I'm still confused as to how to view several of the pages when using localhost. When i run this on my machine I'm able to get to the login page but not anywhere else.
use devise easier, a lot of things misleading.
Even the devise documentation suggests rolling your own to begin with !