This is the third part of the “has_secure_password” Feature in Rails. This post explains how to signin or signout to/from your application. Please read the previous posts (Overview and Signup).
1. Add Controller
Authentication is managed with “Session“. So you need a controller to handle this.
> rails g controller Sessions
2. Configure Routes
In the “config/routes.rb” file, add the following code.
resources :sessions, only: [:new, :create, :destroy] match '/signin', to: 'sessions#new', via: 'get' match '/signout', to: 'sessions#destroy', via: 'delete'
3. Add Actions
The “User” model provides “authenticate” method. By creating or deleting a session, you can practically login or logout a user.
class SessionsController < ApplicationController def new end def create user = User.find_by(email: params[:session][:email].downcase) if user && user.authenticate(params[:session][:password]) session[:user_id] = user.id flash[:success] = "Successfully Logged in" redirect_to user else flash.now[:warning] = "Invalid email or password" render "new" end end def destroy session[:user_id] = nil flash[:info] = "Logged out!" redirect_to root_url end end
4. Login form
Add the “new.html.erb” file to the “views/sessions” folder.
</pre> <h2>Sign in</h2> <div class="row"> <div> <%= form_for(:session, url: sessions_path, html: { class: "form-horizontal" }) do |f| %> <div class="form-group"> <%= f.label :email, class: "col-sm-2 control-label" %> <div class="col-sm-6"><%= f.text_field :email %></div> </div> <div class="form-group"> <%= f.label :password, class: "col-sm-2 control-label" %> <div class="col-sm-6"><%= f.password_field :password %></div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-6"><%= f.submit "Sign In", class: "btn btn-large btn-primary" %></div> </div> <% end %> </div> </div> <div class="row"> <p>New user? <%= link_to "Sign up now!", new_user_path %></p> </div>
5. Helpers
In the “helpers/sessions_helper.rb” file, add the following methods.
module SessionsHelper def current_user @current_user ||= User.find(session[:user_id]) if session[:user_id] end def signed_in? !current_user.nil? end end
To make this helper methods available in all controllers, add the following code to the “controllers/application_controller.rb”
class ApplicationController < ActionController::Base protect_from_forgery with: :exception include SessionsHelper end
6. Signin/Signout Link
You can create a link using the helper method.
<% if signed_in? %> <li><%= link_to current_user.name, current_user %></li> <li><%= link_to "Sign Out", signout_path, method: :delete %></li> <% else %> <li><%= link_to "Sign In", new_session_path %></li> <% end %>