A Simple Authentication with Ruby On Rails

When building a web app, you don't want every user to have access to every single part of the app, so you will want to restrict access. That's why we add authentication to our app. In this tutorial, we will create a simple authentication for your Ruby On Rails app.
PREREQUISITES
To follow along with this tutorial, you will need:
  • Some basic knowledge of Ruby On Rails
  • A text editor(I am using sublime text)
  • Ruby, Rails, Node and Yarn installed on your computer.
  • SET UP
    To get started, create a new rails application and navigate to the directory:
    rails new authentication
    cd authentication
    Next, create a welcome page and set the root to index action in WelcomeController.
    WELCOME PAGE
    To do this, run the following command:
    rails g controller welcome index
    Now, let's set up the route in config/routes.rb like so:
    Rails.application.routes.draw do
    
      get 'welcome', to: 'welcome#index'
      root to: 'welcome#index'
    end
    The generator creates a welcome_controller.rb file in app/controllers
    class WelcomeController < ApplicationController
    
      def index
      end
    
    end
    It also creates an index.html.erb file in app/views/welcome. By default, rails render a view that corresponds with the name of the controller. Now, add some content for that page in the file:
    <h1>Welcome Page</h1>
    BCRYPT
    In the database, we will not like to store our passwords in plain text. Instead, we encrypt the password. We can do this by uncommenting gem 'bcrypt', '~> 3.1.7' in Gemfile and run bundle install to install the gem.
    gem 'bcrypt', '~> 3.1.7'
    bundle install
    Let's continue by adding the model and controllers.
    MODEL
    Create a user model with attributes, email and password_digest
    rails g model User email:string password_digest:string
    And run rails db:migrate to migrate it to the database. The email stores the email address of the user. Also, password_digest creates a password_digest field in the users table.
    In app/models/user.rb, add has_secure_password and some validations.
    class User < ApplicationRecord
        has_secure_password
    
        validates :email , presence: true, uniqueness: true
    end
    Here, before a user gets saved to the database, an email should be present, and it should also be unique.
    REGISTRATION CONTROLLER
    Let's create a registration controller by running the following command:
    rails g controller registrations new
    Add the following to app/controllers/registrations_controller.rb
    class RegistrationsController < ApplicationController
      def new
        @user = User.new
      end
    
      def create
        @user = User.new(user_params)
    
        if @user.save
          session[:user_id] = @user.id
          redirect_to root_path
          else
           render :new  
        end
      end
    
      private
    
      def user_params
        params.require(:user).permit(:email, :password, :password_confirmation)
      end
    end
    The code snippet above creates a new user and saves it to the database. The new action initializes a new object in the User model and stores it as an instance variable that can be accessed in the views. The create action creates the user instance and sets its id to a session which redirects to the root_path if successful and renders new when it fails.
    Create a sign_up form in app/views/registrations/new.html.erb.
    <%= form_with model: @user, url: sign_up_path do |f|  %>
        <%= f.label :email %>
        <%= f.text_field :email %>
    
        <%= f.label :password %>
        <%= f.password_field :password %>
    
        <%= f.label password_confirmation %>
        <%= f.password_field :password_confirmation %>
    
        <%= f.submit "Sign Up" %>
    <% end %>
    and update the route:
    Rails.application.routes.draw do
    
      get 'welcome', to: 'welcome#index'
      root to: 'welcome#index'
    
      resources :users
    
      get 'sign_up', to: 'users#new'
      post 'sign_up', to: 'users#create'
    
    end
    Now, run $ rails s to start the development server and visit localhost:3000/sign_up to create a new user.
    SESSIONS CONTROLLER
    Create the sessions controller by running the code:
    rails g controller sessions new create destroy
    and add the following code to app/controllers/sessions_controller.rb:
    class SessionsController < ApplicationController
      def new
      end
    
      def create
        user = User.find_by(email: params[:email])
    
        if user.present? && user.authenticate(params[:password])
           session[:user_id] = user.id
           redirect_to root_path
        else
            render :new
        end
      end
    
      def destroy
        session[:user_id] = nil
        redirect_to sign_in_path
      end
    end
    The create method for SessionsController finds the user based on the email in the database. If a user is present and the password matches, the id of the user instance is stored in a session and they are logged in. Otherwise, we will be redirected to the sign_in page.
    The destroy method sets the user session to nil and logs out the user.
    In app/views/sessions/new.html.erb, add:
    <h1>Sign In </h1>
    
    <%= form_with url: sign_in_path do |f| %>
    
        <%= f.label :Email %>
        <%= f.text_field :email %>
    
        <%= f.label :Password %>
        <%= f.password_field :password %>
    
        <%= f.submit "Sign in" %>
    <% end %>
    and set up the routes:
    Rails.application.routes.draw do
    
      get 'welcome', to: 'welcome#index'
      root to: 'welcome#index'
    
      resources :users
    
      get 'sign_up', to: 'users#new'
      post 'sign_up', to: 'users#create'
    
      get 'sign_in', to: 'sessions#new'
      post 'sign_in', to: 'sessions#create'
      delete 'logout', to: 'sessions#destroy'
    
    end
    Now, a user can sign_in by visiting localhost:3000/sign_in in the browser.
    Current.user
    Add the following in app/controllers/application_controller.rb to create a Current.user
    class ApplicationController < ActionController::Base
        before_action :set_current_user
    
        def set_current_user
          if session[:user_id]
           Current.user = User.find_by(id: session[:user_id])   
          end
        end
    end
    The set_current_user method will return the current user if it finds one or if there is a session present. Also, since all controllers inherit from the ApplicationController, set_current_user will be accessible in all the controllers.
    Let's create a current.rb file in app/models and add the following:
    class Current < ActiveSupport::CurrentAttributes
    
      attribute :user
    
    end
    This code will allow us to call Current.user in our views.
    Now, Open app/views/welcome/index.html.erb and update it with the following:
    <h1>Welcome Page</h1>
    
    <% if Current.user %>
      Logged in as: Current.user.email<br>
      <%= button_to "Sign Out", logout_path,  method: :delete %>
      <% else %>
      <%= link_to "Sign up", sign_up_path %>
      <%= link_to "Sign In", sign_in_path %>
    <% end %>
    This code checks if Current.user is present and provides a sign_out button when signed in. Otherwise, a sign_up and sign_in link is seen.
    CONCLUSION
    Congrats, we have successfully built a simple authentication in Ruby On Rails without relying on any gem. I hope you found this tutorial easy to follow, and If you have any questions, please add your query in the comments section. Thank you!

    41

    This website collects cookies to deliver better user experience

    A Simple Authentication with Ruby On Rails