Migrate from Rails built in authentication to Devise Gem

Written by Indigo Tech Tutorials

August 28, 2025

1 views

Today I am migrating my app from the rails built in authentication to use the devise gem the reasons are covered in my previous article. Mainly because I need a second model for user authentication and extending the code provided by authentication generator is too difficult. I was going to just duplicate all of the code and models ( Authentication concern, Session and Current model over to my scoped user account ) but this seems like a bad approach.

Instead I have decided to switch to use the devise gem which is well maintained and reliable with tons of essential features built in. I want to document my steps for anyone else wanting to do this.

The first step is to remove the code that is added by the authentication generator. First I removed the sessions table from the database by creating a migration file

rails g migration remove_sessions

This created a migration file in the db/migrate folder and inside of this new file I added the following code

class RemoveSessions < ActiveRecord::Migration[8.0]
  def change
    drop_table :sessions
  end
end

Then I was able to run the migrate command -- rails db:migrate -- to migrate the database and this table was removed. Next I went and deleted the session model and the current model which is not backed by a database table so no migration is needed X app/models/session.rb X app/models/current.rb

You should also remove the relation to sessions from the user model so in app/models/user.rb remove the has_many :sessions line

We can also remove the has_secure_password line from the user model since devise will not use this it has its own password solution.

Next lets look at updating the users table to have the correct fields needed by devise. Lets generate a new migration file to handle the new changes and additions

rails g migration changing_users_to_devise

Inside of this migration file we want to rename the email_address column to email. Devise uses the field encrypted_password so we can add this new field or just rename are password_digest field. Lets go for renaming the existing field but we will have to reset all of the passwords in our app anyways. Then we also need to add the fields for remember password and reset_password_token. The final migration file should look like this

class ChangingUsersToDevise < ActiveRecord::Migration[8.0]
  def change
    rename_column :users, :email_address, :email
    rename_column :users, :password_digest, :encrypted_password
    add_column :users, :reset_password_token, :string
    add_column :users, :reset_password_sent_at, :datetime
    add_column :users, :remember_created_at, :datetime
    add_index :users, :reset_password_token, unique: true
  end
end

Now we need to add the devise methods to user model. In app/models/user.rb add this code

devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

To add all of the routes needed we need to go to config/routes.rb and add this line

devise_for :users

At this point I want to test if the code worked so I ran bin/dev and got this error uninitialized constant ApplicationController::Authentication This is because I removed the Authentication concern but I am still including it inside the application_controller. So make sure you remove any includes of this helper which should only be in application_controller. Now reloading you will see more errors because of references to methods that were used by the authentication generator make sure to remove these references and replace them with devise equivalents. :require_authentication -> :authenticate_user! and resume_session is no longer needed because I was using this to ensure the current_user method would get loaded but with devise this is already done without any changes needed!

What I did for this is add before_action :authenticate_user! to my app/controllers/application_controller.rb file and then did a search for any controllers which were using the skip_before_action :require_authentication which meant a user account is not needed and replace it with skip_before_action :authenticate_user!

A another thing is to replace anywhere still using Current.user to current_user

Another thing to replace is the method allow_unauthenticated_access on the controllers replace this with skip_before_action :authenticate_user!

The last step is to move your sign_up and sign in views. The HTML and styling for these pages over to use the devise forms. We can do this by copying the devise views to local and then updating them with our code

rails g devise:views

Also make sure anywhere referencing the old email_address field is updated to use email since we renamed that. Things like validations on user model and places in the views

We can remove the normalize email line from the user model because devise should handle this for us I'm pretty sure we can remove the validations enforcing user email to be present and unique as devise also does this. So remove all of these lines from app/models/user.rb

validates_presence_of :email
validates_uniqueness_of :email
normalizes :email_address, with: ->(e) { e.strip.downcase }

Now for simplicity I am going to update all of the users passwords to a basic string so I can access the accounts again. In a production app if you already have users you would want to create some sort of rake task that updates the password to a random secure string and then emails them with the new password and telling them to update their password. But for development it is not real users so this works

User.find_each { |u| u.update(password: "123456") }

Another thing you need to do is anywhere you are using start_new_session_for you need to replace with the devise version of the method sign_in start_new_session_for(user) -- Change to ---> sign_in(user)

Become a member to gain exclusive mentorship

Start now

More blog posts