Rails 5: User accounts with 3 types of roles – Devise, Rails_admin, Cancancan

Article presents how to set up a user accounts for 2 types of end-users’ roles and 1 admin role. Users with admin roles have access to Rails_admin dahsboard. Authentication is done by Devise gem and authorization is set up by Cancancan gem.

Ruby: 2.3.0



Let’s assume that Rails project with basic elements is already initialized and works on MySQL database.



  1. Create User model using Devise gem
  2. Setup authentication by Devise gem
  3. Generate views, links and controllers for Devise’s Users
  4. Create rails_admin dashboard
  5. Set up authorization using Cancancan
  6. Give access to rails_admin only for admin (superadmin) users using Cancancan
  7. Setup mailer for Devise


User accounts – Devise

Devise installation

Open Gemfile and add:

Run bundler and then Devise generator:

It prompts few instructions which we have to do manually. First, add to config/environments/development.rb:

Instead of localhost you can put IP of your machine and you can replace port number 3000 if your app uses different.

Next we should set a root_url in config/routes.rb. Probably you have done it already, but if not, let’s do this now: (config/routes.rb):

The third instructions is about flash messages, which notifies about successful and failed login attempts. We will use for this a toastr gem.

Add to Gemfile:

To application.css and application.js add the following:

To display devise notices and alerts via toastr, add the following code to  app/views/layouts/application.rb:


Devise generator

In next step, we can generate User model:

Let’s add a new test account before running migration. Open db/migrate/xxx_devise_create_user.rb and add:



Authenticate user

Let’s assume that our application has:

  • landing page – available for anyone – in our example app it can be home#index (index action of home controller),
  • dashboard – this is available only for logged users – user have to sign in to see this area of app.

Let’s add following to app/controllers/application_controller.rb:

authenticate_user placed in application_controller.rb forces an authentication before each action of any controller. You can verify it now by opening any page of your app in web browser. Instead of the desired page, you should see the login form. But we want that landing page should be available without any authentication. So open landing controller, for example app/controllers/home_controller.rb and add following to skip authenticate_user for index action:

Now you should see your landing page without any authentication.

Do you remember that we’ve created a test user account during migration with following params?

  • email: test@test.com
  • password: password

You can now try to open another page and enter this to login form to get access to restricted area of your app.


Links and redirections

In this part we will prepare some basic views and links. Let’s start by adding a link to login form to our landing page:

Not signed user will see the Sign in button and would be redirected to login form. Already signed users will see Go to App button which redirects to application dashboard.

You can meet a little problem now. If you are at the landing page, then click on the Sign in button and successfully sign in, you will be redirected back to landing page. But we would like to redirect users directly to dashboard. To do that, we have to overwrite the after_sign_in_path_for method. Open app/controllers/application_controller.rb and add this:

Instead of app_dashboard_index_path you can put path to your page from restricted part of app.

The other links which you should use in your app are presented below. You can use also user_signed_in? method to determine if user is already signed in.



To overwrite views, you have to run following devise command:

The set of views is placed under app/views/users/*. In this article we skip the process of customizing forms, but you can make it now.



Let’s use following command to generate and customize devise controllers:

If you are using custom controllers, you have to set routes in config/routes.rb:


Admin Users – rails_admin gem

Add to Gemfile:

And run:

Now you should get access to rails_admin dashboard under /admin in web browser.


You can customize rails_admin gem in config/initializers/rails_admin.rb. To use devise for authentication purpose, add following:


Authorization – CanCanCan

We use CanCanCan gem to restrict access to some parts of app for users with specific roles. Add to Gemfile:

And run bundler. Next, use following command to genrate ability class:

In file app/models/ability.rb, you can define abilities. But first, we have to set users different roles. It’s up to you how you want to define roles. We will add to user’s model a three boolean columns for three roles: superadmin, supervisor, user. Let’s start by generating migration:

Before we run migration, let’s edit it. Open it (db/migrate/xxx_add_roles_to_users.rb):

We’ve defined default values for superadmin and supervisor as false, and true default value for user_role. Now we can run:

To verify current user role, you can use:


To display some elements only for users with specific role, you can use:

Or you can use CanCanCan abilities:

And in app/model/ability.rb:



To authorize user access to controller’s actions, let’s add following to specific contoller:

It will use a before action to load the resource into an instance variable and authorize it for every action.


Rails_admin and Cancancan

In this part, we set access to our /admin dashboard only for superadmin users. First, we have to configure config/initializers/rails_admin.rb:

Next, let’s modify app/model/ability.rb:



Devise has to send “reset password” and “confirmation” (if unlocked) emails to users. We’ll set also to send welcome email after registration.

First, we have to configure an access to email account. You can use your personal email account, like gmail. Open config/environments/development.rb and add / modify following:

Next, we add mail_username  and mail_password to config/secrets.yml:

Replace test@example.com and Password123 with your data.

In config/initializers/devise.rb you can modify default mailer sender:

Now you can try to reset a password. Open in web browser: /users/password/new . And try to send reset password instructions. If you’ve got an error for gmail account: Net::SMTPAuthenticationError, please follow this solution from stackoverflow.

Last thing is a welcome email, which should be send after creating a new user account. Add to the User model app/models/user.rb:

Generate UserMailer:

Add to app/mailers/application_mailer.rb:

Now we have to create mailer views in html and text formats. Create two files in app/views/user_mailer/ directory: send_welcome_email.html.erb:

… and send_welcome_email.text.erb:

Now you can test it by singing up to application or create new user account manually by your rails_admin dashboard.





Tomasz Antas

Ruby on Rails developer and Web designer.
The area of his interest includes Popular Science, Internet of Things, Wearables, AI and Virtual/Augmented Reality.

Latest posts by Tomasz Antas (see all)

Thanks for reading!

  • DavidT

    Hi Tomasz, I just came across this site and am blown away. The topics are relevant and your explanations are clear and concise.
    Thanks so much for pointing out toastr.

    • Tomasz Antas

      Thank you for your kind words!

  • Tyson Buzza

    I’m pretty new to RoR, why toastr? The flash messages seem to work fine without it, what does it do?

    • Tyson Buzza

      I think I’m using bootstrap instead, is there a reason to use toastr still?

      • Tomasz Antas

        Toastr is not required, I’ve used it just for fun in this article 😉 Typical flash messages are fine as well. There is also a lot of similar javascript messaging “tools/libraries”. I cannot recommend any outstanding one, but I believe that it wouldn’t be a problem to find an alternative for toastr.

        • Tyson Buzza

          Just noticed something else, the version of rails_admin you are using has a known security issue. Might be worth adding a comment mentioning this?

  • Suchat Tangjarukij

    How can I edit super_admin_role, because I can only create a normal user.

    • Tomasz Antas

      You want create an user with super_admin_role?

      • Bong Kum Tim

        Hi Tomasz, how do i create super_admin or supervisor ?

        • Bong Kum Tim

          thank Tomasz, i create it using rails console. Your code is simple and nice. Appreciate a lot of your fast reply too! Thanks bro!

          • Tomasz Antas

            NP, Thanks for a kind word!

  • Pingback: replique van cleef & arpels pour homme()

  • Alex

    Hello Tomasz,
    nice write-up!
    I have to add authorization to an existing app and your article made me feel less overwhelmed :)
    Keep up the good work!

  • Hello, why if in ability.rb set next rights:

    if user.manager_role?
    ____ can :show
    ____ can :access, :rails_admin # grant access to rails_admin
    ____ can :dashboard

    not allow to enter into RailsAdmin Panel? There is an error: CanCan::AccessDenied in RailsAdmin::MainController#dashboard (print-screen attached)

    Hope on your help, Tomasz :-)


  • Daniel Reidy

    amazing article. The best way to get started with rails and devise. Thanks for all the tips.

  • Ben Edwards

    Great article.

    I had to add the flowing to the beginning of ability.rb. Seem to work but wondering if this is OK.

    config.authenticate_with do
    warden.authenticate! scope: :user

    The problem I was having was that user was nil even if I was logged i.

  • Clint326

    Hi. Thanks for the great article! I’m using Ruby 2.4.0p0 and Rails 5.1.4. When follow along with your example and try ‘rails g cancan:ability’ I get the following error:

    undefined method `authenticate_with’ for Devise:Module
    Did you mean? authentication_keys (NoMethodError)


    • Tomasz Antas

      Have you set up the “authenticate_with” method anywhere? I’ve used it in:


      (You can find it in this tutorial in section “Admin Users – rails_admin gem”)

      • Clint326

        That worked! Thanks.

  • Pingback: Devise, CanCanCan y RailsAdmin – Gairga()

  • praaveen

    Good Article Tomasz.
    Here we designed Authentication and Authorization for rails 5 application which uses active admin, devise and cancancan gem.

    This may help to some to get ready with authentication and authorization in rails. Here is the link

  • Chidozie Nnachor

    Hi Tomasz.

    Thank you for your tutorial. I find it simple enough yet I cannot get it to work on my existing app. I think the issues I have stem from the fact that my User model is not name “User”. So I can’t really figure out when to take the code as is, and when to change occurrences of “user” for my own model name. For instance in the rails_admin.rb and ability.rb files.

    If I switch “user” with my model name, the code breaks. If I don’t I get a “undefined method `failure_app’ for nil:NilClass” Error.

    Can you help?

    • Tomasz Antas

      Hello Chidozie,
      sure, I’ll try to help you :)

      To make it more clear, let’s assume that the name of your model is “Customer”, ok?

      So, let’s try this:
      1) In config/initializers/rails_admin.rb:

      config.authenticate_with do
      warden.authenticate! scope: :customer

      2) To add new columns to database in migration, use “customers” instead “users”:

      add_column :customers, :superadmin_role, :boolean, default: false

      3) To verify current user / customer role, use:


      4) To check if that user / customer has access to specific resource:


      5) In ability.rb you can replace “user” with “customer” and “User” with “Customer”:

      class Ability
      include CanCan::Ability

      def initialize(customer)
      # Define abilities for the passed in user here. For example:

      customer ||= Customer.new
      if customer.superadmin_role?
      can :manage, :all
      if customer.supervisor_role?
      can :manage, Customer



      I hope this helps you :) If you get more problems, let’s try to make it step by step. I’m aware that might not be trivial ’cause you are working on existing project. However, you can start with setting up Rails Admin with your model. When Rails Admin will work, we can go to the next step and handle the CanCanCan.

      • Chidozie Nnachor

        Thank you so much.

        I took your advice and “took it slowly” rather than try to set up everything in one go. Right now I have the rails_admin panel working just fine. The devise setup hasn’t thrown any errors (yet) so I assume it is working too as right now I have no idea the effect :)

        I will revert if I succeed in setting up cancancan.

        Thank you again.

      • Chidozie Nnachor

        So I finally got it.

        After following everything step by step, I still get an “undefined method” error. So I searched further and found out I needed to change the default declaration of cancancan Ability from “current_user” to my model specific version (here: https://github.com/CanCanCommunity/cancancan/wiki/changing-defaults)

        So in the application_controller.rb:

        alias_method :current_user, :name_of_your_method # Could be :current_member or :logged_in_user

        That solved my final error message.

        Thanks bruv.

        • Tomasz Antas

          I’m glad that you solved it! :)

  • Jeppe

    Is the supervisor can manage user cant he make himself a super_admin?