Create a Blog Application with Ruby on Rails 7. Third Part: Implement User Authentication

Last updated on September 6, 2022

In this blog post, we’ll continue developing our blog application by implementing user authentication.

All Parts:

  1. Create a Blog Application with Ruby on Rails 7. First Part: Create the User Resource
  2. Create a Blog Application with Ruby on Rails 7. Second Part: Create a Post Model and a Posts Controller
  3. Create a Blog Application with Ruby on Rails 7. Third Part: Implement User Authentication
  4. Create a Blog Application with Ruby on Rails 7. Fourth Part: Performing Operations on the Post Resource
  5. Create a Blog Application with Ruby on Rails 7. Fifth Part: Implement Authorization

FIND THE CURRENT USER

Let’s first define a @_current_user method to find the user with the id stored in the session.

In the application_controller.rb file in the app/controllers/ directory, we add the following private method:

private
def current_user
@_current_user ||= session[:current_user_id] &&
User.find_by(id: session[:current_user_id])
end

And we set it as a before filter in the before_action method of the same controller. At the top, we put this line:

before_action :current_user

Next, we will build a mechanism to add and remove the user from the session. Let’s generate a Sessions controller. In the terminal, we type:

bin/rails g controller Sessions

In the app/controllers/sessions_controller.rb file, we will define the new and create methods:

def new
end
def create
user = User.find_by(email: params[:email])
if user != nil && user.authenticate(params[:password])
session[:current_user_id] = user.id
redirect_to root_path
flash[:notice] = 'Welcome back.'
else
redirect_to log_in_path
flash[:notice] = 'E-mail and/or password is incorrect.'
end
end

The authenticate method returns the user if the password is correct and false otherwise. 

We need routes for these actions, so let’s add them to the config/routes.rb file:

get 'log-in', to: 'sessions#new'
post 'log-in', to: 'sessions#create'

 In the app/views/sessions/ folder, we create a new view where we’ll put the login form and a link to the sign-up page in case the user doesn’t have an account:

<p style="color: green"><%= notice %></p>
<h1> Log In </h1>
<p>Or <%= link_to 'Sign Up', sign_up_path %></p>
<%= form_with url: log_in_path do |form| %>
<p><%= form.label :email %></p>
<p><%= form.email_field :email, required: true %></p>
<p><%= form.label :password %></p>
<p><%= form.password_field :password, required: true %></p>
<p><%= form.submit 'Log In' %></p>
<% end %>

Next, we’ll create a destroy action so the user can log out. Let’s define it in the Sessions controller:

def destroy
session.delete(:current_user_id)
@_current_user = nil
redirect_to root_path
flash[:notice] = 'Goodbye.'
end

And we define a route to it in the config/routes.rb file:

delete 'log-out', to: 'sessions#destroy'

Finally, let’s edit the posts index view to add a login and a signup button if there is no user in the session and a logout button if the user is logged in. Let’s put these buttons before the h1 heading:

<% if @_current_user %>
<%= button_to 'Log Out', log_out_path(@_current_user), method: :delete %>
<% else %>
<%= link_to 'Log In', log_in_path %>
<%= link_to 'Sign Up', sign_up_path %>
<% end %>

Now, in the Users controller, we can redirect the user to the log-in page after a successful registration. Let’s modify the create method as follows:

def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
format.html {redirect_to log_in_path, notice: 'User was successfully created.'}
else
format.html { render :new, status: :unprocessable_entity }
end
end
end