Devise is a gem that makes it easy to add authentication in Rails. Using the gem, you can create the User model and the corresponding login/logout views in a matter of minutes as opposed to creating the entire authentication flow from scratch. Let’s take a look at how it works.


First, instantiate a new Rails app. Note - I’ll be using Rails 7 for the demo.

rails new devise-demo
cd devise-demo

This will create a simple vanilla Rails installation. Let’s add the devise gem to the application.

#Gemfile
...
gem "devise"

Then run bundle install and install devise

bundle install
rails generate devise:install

After installing devise:install, Rails will helpfully prompt us to do a few steps of setup

Depending on your application's configuration some manual setup may be required:

1. Ensure you have defined default url options in your environments files. 
Here is an example of default_url_options appropriate for a development environment 
in config/environments/development.rb:

  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

In production, :host should be set to the actual host of your application.

  * Required for all applications. *
  
2. Ensure you have defined root_url to *something* in your config/routes.rb.

For example:
root to: "home#index"

* Not required for API-only Applications *

3. Ensure you have flash messages in app/views/layouts/application.html.erb.

For example:

<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

* Not required for API-only Applications *

4. You can copy Devise views (for customization) to your app by running:

rails g devise:views

* Not required *

Let’s follow the suggestions and make the necessary changes

#config/environments/development.rb
...
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

We will also a controller called pages with an action of home and set it as the default root route

rails g controller pages home

Now, we will make the pages#home route as the root path

#routes.rb
Rails.application.routes.draw  do
    root "pages#home"
end

We will also add the flash messages in application.html.erb

#application.html.erb

...
<body>
  <p  class="notice"><%= notice %></p>
  <p  class="alert"><%= alert %></p>
  <%= yield %>
</body>

While Devise has been initalized, we still need to generate the User model. With Devise, this can be done easily

rails generate devise User

We can take a look at the migration file generated by this command

# frozen_string_literal: true

class  DeviseCreateUsers < ActiveRecord::Migration[7.0]
	def  change
		create_table :users  do |t|
			t.string  :email, null:  false, default:  ""
			t.string  :encrypted_password, null:  false, default:  ""
			t.string  :reset_password_token
			t.datetime  :reset_password_sent_at
			t.datetime  :remember_created_at
			t.timestamps  null:  false
		end

		add_index :users, :email, unique:  true
		add_index :users, :reset_password_token, unique:  true	
	end
end

Devise creates the email, encrypted_password, reset_password_token, reset_password_sent_at and remember_created_at fields by default. Other fields can also be enabled as mentioned in the documentation.

This will also create a set of associated user routes which can be viewed by running

rails routes | grep user

Devise also helpfully provides a set of views which we can generate by running

rails g devise:views

Devise as of writing this has not adapted to Rails 7 so we need to make a few modifications to the views.


<!-- app/views/devise/registrations/new.html.erb -->  
<!-- [...] -->  
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), data: {turbo: false}) do |f| %>
<!-- app/views/devise/sessions/new.html.erb -->  
<!-- [...] -->  
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: {turbo: false}) do |f| %>

Now head over to http://localhost:3000/users/sign_up. You should see the signup form. Enter your details and you should get redirected to the root path with a message saying that you have successfully logged in