Create a Blog Application with Ruby on Rails 7. Third Part: Implement User Authentication
In Ruby on Rails Sep 6, 2022
Updated on Dec 17, 2023
In this blog post, we'll continue developing our blog application by implementing user authentication.
All Parts:
- Create a Blog Application with Ruby on Rails 7. First Part: Create the User Resource
- Create a Blog Application with Ruby on Rails 7. Second Part: Create a Post Model and a Posts Controller
- Create a Blog Application with Ruby on Rails 7. Third Part: Implement User Authentication
- Create a Blog Application with Ruby on Rails 7. Fourth Part: Performing Operations on the Post Resource
- 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