How to Setup Devise for User Authentication on Rails 7
Tags: webdev, ruby, rails, fullstack
Published: 2023-03-20 22:36:08

If you are a frequent user of Ruby on Rails, you know that building authentication and user management systems can be a time-consuming and complex process. That’s where Devise comes in — a powerful authentication solution that simplifies the process of implementing user management systems in your Rails applications. As a Rails developer who churns out apps regularly, I’ve found myself reaching for Devise every single time. However, with the release of Rails 7, I’ve had to adjust my workflow and make sure that Devise works seamlessly with the new version. In this blog post, I’ll share my workflow for setting up Devise on Rails 7 and walk you through the steps to get started with this essential tool. So, whether you’re a seasoned Rails developer or just getting started, read on for a comprehensive guide to setting up Devise on Rails 7.

## Hang on, why should I use Devise?


![Devise logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/drb9llzq6ka4hb4ekmn7.png)

Authenticating users in a web application is a critical task that requires careful consideration of security best
practices. Building authentication functionality from scratch can be a daunting and time-consuming process, particularly
for developers who are not well-versed in security principles. This is where Devise comes in handy. Devise provides a comprehensive and customizable solution that handles common authentication tasks such as user registration, login, and password resets, while also supporting various authentication mechanisms and providing robust security features. By using Devise, developers can save valuable time and ensure their application's authentication system is strong and reliable, allowing them to focus on building other aspects of their application. Let's see it in action on Rails 7.

## Prerequisites

Before proceeding with the guide, ensure that you have a new or barebones Rails app created using `rails new`.
Additionally, you should not have a `User` model set up yet.

## Step-by-Step Guide

- Add Devise, Letter Opener, and Omniauth (optional) to your Gemfile:

    ```ruby
    ...
    gem "devise", github : "heartcombo/devise", ref : "f8d1ea90bc3"
    gem "omniauth"
    ...
    group :development do
        ...
        gem "letter_opener"
        ...
    end
    ```

   Note: cloning Devise from GitHub is necessary because it contains fixes for some Rails 7 incompatibilities.

- Install the gems:
    ```bash
    bundle install
    ```

- Run the Devise install generator:

    ```bash
    rails g devise:install
    ```

   This generates the `devise.rb` initializer and adds the `en` locale at `config/locales/devise.en.yml`.

- Add the following Devise-specific configurations to `config/development.rb`:

    ```ruby
    # For Devise
    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
    # For Letter Opener
    config.action_mailer.delivery_method = :letter_opener
    config.action_mailer.perform_deliveries = true
    config.action_mailer.raise_delivery_errors = true
    ``` 

- Generate the `User` model with Devise:

    ```bash
    rails g devise user
    ```

   This creates the user model files as well as a preliminary migration.

- Edit the migration to add the fields you need:

    ```ruby
    ## Identifying fields
    t.string :first_name, null : false, default : ""
    t.string :last_name, null: false, default: ""
    ```

   Also, uncomment the `trackable`, `confirmable`, and `lockable` fields (and accompanying indexes).

- Edit `user.rb` and add `confirmable`, `trackable`, `lockable`, and `omniauthable` to Devise.
- Tweak options in `config/devise.rb` to suit your needs. For example, you may want to increase the `remember_for`
   option to a couple of months:

    ```ruby
    config.remember_for = 2.months
    ```

   In the same file, change the default email to one from your application:

    ```ruby
    config.mailer_sender = 'no-reply@designerdiscount.club'
    ``` 

- Generate the Devise views so you can modify them later:

    ```
    rails g devise:views
    ``` 

- Migrate the database:

   ```bash
   rake db:migrate
   ``` 

- Add the following code to `application.html.erb` right above the `yield` block:

   ```erb
   <% if notice %>
     <p class="alert alert-success"><%= notice %></p>
   <% end %>
   <% if alert %>
     <p class="alert alert-danger"><%= alert %></p>
   <% end %>
   ``` 

- Try it out! Start your rails server and head to http://localhost:3000/users/sign_up and create a new user. You should receive an email which opens in the browser (via letter_opener). Great, it’s working!

- Deny logged-out access to a controller action and test it out. Create a `home` action in an existing controller,
   which is `PagesController` in this example:

   ```ruby
    
   class PagesController < ApplicationController
     def landing; end
    
     def home; end
   end
   ```

   Let’s redirect the user to the landing page if they try to access `home` but are logged out.

   ```ruby
    
   def landing
     redirect_to(action: :home,
                 params: request.query_parameters) if user_signed_in?
   end
    
   def home
     redirect_to(action: :landing,
                 params: request.query_parameters) unless user_signed_in?
   end
   ``` 

- Edit the global header to hide the sign-in link if the user is signed in:

    ```erb
    <% if user_signed_in? %>
      <li class="flex">
        <%= link_to 'Logout', destroy_user_session_path,
                    method: :delete,
                    data: { turbo_method: :delete } %>
      </li>
    <% else %>
      <li class="flex">
        <%= link_to "Sign up", new_user_registration_path, rel: 'noopener noreferrer' %>
        <%= link_to "Login", new_user_session_path, rel: 'noopener noreferrer' %>
      </li>
    <% end %>
    ``` 

That’s it! You now have a basic setup for user authentication using Devise on Rails 7. You can customize the generated Devise views with Tailwind or Bootstrap to match your app’s design. Want to learn more? Check out the [Devise wiki](https://github.com/heartcombo/devise#the-devise-wiki). Preparing for a coding interview? Check out [Firecode.io](https://firecode.io).