Create Login in Ruby on Rails
Tags: rails, ruby, beginners, webdev
Published: 2022-05-09 08:49:02

Want a simple login for your rails app? I'll cover that in this tutorial.

We will require the user to login in order to gain access to certain pages. Take note that this is a simple login, user roles and authentication won't be covered in this post.

First, we will create simple pages to demonstrate the website requiring the user to log in.

## Create Pages
   I'll create two pages, admin and home.

   Create the views, `admin.html.erb` and `home.html.erb`  at `app/views/pages/`.

   ```html
    // app/views/pages/admin.html.erb
    
   <h1>Admin Home</h1>
   <p>app/views/pages/admin.html.erb</p>
   ```

   ```html
    // app/views/pages/home.html.erb
    
   <h1>Home</h1>
   <p>app/views/pages/home.html.erb</p>
   ```

   Now create the controller for these pages at `app/controllers/`.

  ```ruby
  # app/controllers/pages_controller.rb
 
  class PagesController < ApplicationController
    def home
    end

    def admin
    end
  end
  ```
  Finally, create routes for these pages.
  
 ```ruby
  # config/routes.rb

  get "/admin" => "pages#admin", as: "admin"

  root "pages#home"
 ```

  The pages should work by checking your localhost. The page for `localhost:3000` should be `app/views/pages/home.html.erb` and `localhost:3000/admin` is `app/views/pages/admin.html.erb`.


## Create Login
 Now the pages were done, we will start implementing a login system. I'll be using [devise](https://github.com/heartcombo/devise) gem. It has all of the things we need for a simple login.

1. Install devise gem by adding this to your Gemfile:
    ```ruby
    gem 'devise'
    ```
    Then run bundle install.

2. Generate necessary files for devise running this in your terminal:
    ```terminal
    $ rails generate devise:install
    ```
    > If you're using rails 7 you may encounter an error. You may need to paste this code in your `config/initializers/devise.rb`: <br>```config.navigational_formats = ['*/*', :html, :turbo_stream]```<br>[source](https://stackoverflow.com/questions/36646226/undefined-method-user-url-for-devise- sessionscontrollercreate)

3. Create the migration files we would be using.
    ```ruby
    $ rails generate devise MODEL
    ```

    Replace `MODEL` with the class name used for the application’s users (I mostly use `User` but could also be `Admin`).

    Then run `rails db:migrate`.

4. Require the user to log in when visiting the admin page.

    You could do this by updating `app/controllers/pages`.
    ```ruby
    class PagesController < ApplicationController
     before_action :authenticate_user!, only: :admin

     def home
     end

     def admin
     end
    end
    ```
    The `before_action :authenticate_user!` will check if the user is logged in. Depending on the model you might need to change to `authenticate_MODEL!`, example, if you chose to name your devise model `Admin` then it should be `authenticate_admin!`. 

    By adding `only: :admin` the action is only performed at admin action(app/views/pages/admin.html.erb). 

That should do it! Restart your server and check it out!

## Add links (Optional)
 In here, I'll add a sign in and sign out links for the website.

1. Create file `_user_detail.html.erb` at`app/views/shared/`.
    ```html
    // app/views/shared/_user_detail.html.erb
    <% if user_signed_in? %>
     <%= button_to("Log Out", destroy_user_session_path, method: :delete) %>
    <% else %>
     <%= link_to 'Log in', new_user_session_path %>
    <% end %>
    ```
    > If you're using rails 7 logout button may not work properly you need to use this: <br> `<%= button_to("Log Out", LOGOUT_PATH, method: :delete) %>` <br> [source](https://dev.to/spaquet/rails-7-devise-log-out-d1n)

    The paths here are the login in and sign out. You could check yours by running `rails routes`.

    The `user_signed_in?` is a helper in devise. It returns true or false depending on if the user is logged in. This might changed depending on the chosen name for the devise model. If you chose `Admin` then it should be `admin_signed_in?`.

2. Add links to `app/views/pages/home.html.erb` and `app/views/pages/admin.html.erb`.
    ```html
    <%= render "shared/user_detail"%>
    ```

References:
- https://stackoverflow.com/questions/36646226/undefined-method-user-url-for-devise-sessionscontrollercreate
- https://dev.to/spaquet/rails-7-devise-log-out-d1n
- https://github.com/heartcombo/devise

You could check out my repository [here](https://github.com/jkevinbaluyot/login-demo).

**Please do not repost**