Multiple Resources with Devise

Episode #290 by Teacher's Avatar David Kimura

Summary

Sometimes we get into situations where our applications requires a different type of user account which wouldn't really fit into a role. So, in this episode we look at creating multiple resources for authentication with Devise.
authentication rails devise 15:48

Resources

Download Source Code

Summary

# Terminal
bundle add devise
rails g devise:install
rails g devise User
rails g devise Admin
rails g controller users/dashboard index
rails g controller admins/dashboard index
rails g devise:controllers users -c=sessions
rails g devise:controllers admins -c=sessions
rails g devise:controllers users -c=registrations
rails g devise:controllers admins -c=registrations

# views/layouts/application.html.erb
      <% if user_signed_in? %>
        <%= link_to 'Sign Out', destroy_user_session_path, method: :delete %> |
      <% elsif !admin_signed_in? %>
        <%= link_to "Sign In", new_user_session_path %> |
      <% end %>

      <% if admin_signed_in? %>
        <%= link_to 'Sign Out as Admin', destroy_admin_session_path, method: :delete %> |
      <% elsif !user_signed_in? %>
        <%= link_to "Sign In as Admin", new_admin_session_path %> |
      <% end %>

# config/routes.rb
Rails.application.routes.draw do
  devise_for :users, path: 'users', controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations'
  }

  devise_for :admins, path: 'admins', controllers: {
    sessions: 'admins/sessions',
    registrations: 'admins/registrations'
  }

  devise_scope :user do
    authenticated :user do
      namespace :users do
        get 'dashboard/index', as: :authenticated_root
      end
    end
  end

  devise_scope :admin do
    authenticated :admin do
      namespace :admins do
        get 'dashboard/index', as: :authenticated_root
      end
    end
  end

  root to: 'welcome#index'
end

# controllers/concerns/accessible.rb
module Accessible
  extend ActiveSupport::Concern
  included do
    before_action :check_resource
  end

  protected

  def check_resource
    if admin_signed_in?
      flash.clear
      redirect_to(admins_authenticated_root_path) and return
    elsif user_signed_in?
      flash.clear
      redirect_to(users_authenticated_root_path) and return
    end
  end
end

# controllers/admins/registrations_controller.rb
class Admins::RegistrationsController < Devise::RegistrationsController
  include Accessible
  skip_before_action :check_resource, except: [:new, :create]
end

# controllers/admins/sessions_controller.rb
class Admins::SessionsController < Devise::SessionsController
  include Accessible
  skip_before_action :check_resource, only: :destroy
end

# controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  include Accessible
  skip_before_action :check_resource, except: [:new, :create]
end

# controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
  include Accessible
  skip_before_action :check_resource, only: :destroy
end