1
votes

I have a user model which uses Devise for authentication and also have an administrator model, which also uses Devise. I want administrators to be able to edit users profile via administrators/users/{user.id}/edit, however I want this process to be done through Devise Controllers, therefore I tried to inherit from the Users::RegistrationsController as shown below:

class Administrators::UsersController < Users::RegistrationsController
before_action :set_user, only: [:show,:edit,:update,:destroy]
def index
    @users=User.all
end
def show
end

def new
    super
end

def update
    @user.update(user_params)
    redirect_to [:administrators,:users]
end

but I get the following error:

Could not find devise mapping for path "/administrators/users". This may happen for two reasons: 1) You forgot to wrap your route inside the scope block. For example: devise_scope :user do get "/some/route" => "some_devise_controller" end 2) You are testing a Devise controller bypassing the router. If so, you can explicitly tell Devise which mapping to use: @request.env["devise.mapping"] = Devise.mappings[:user]

I tried to change the routes but I still get the same error. Could you please help me?

1

1 Answers

2
votes

Inheriting from Devise::RegistrationsController may initially seem like a good idea from a code reuse standpoint but it really not a very good idea.

The intent of the controllers is very different - Devise::RegistrationsController partially deals with an un-authenicated user - and the Devise controllers are scary beasts due to the amount of flexibility built in Devise.

Instead you should just setup a plain old CRUD controller as the task at hand is not very complex compared to clobbering over half of Devise::RegistrationsController.

# config/routes.rb
namespace :administrators do
  resources :users
end

# app/controllers/administrators/base_controller.rb
module Administrators

  class AuthorizationError < StandardError; end

  class BaseController
    respond_to :html
    before_action :authenticate_user!

    # Replace with the lib of your choice such as Pundit or CanCanCan
    before_action :authorize_user! 
    rescue_from AuthorizationError, with: :unauthorized

    private 

       def authorize_user!
         raise AuthorizationError and return unless current_user.admin?
       end

       def unauthorized
         redirect_to new_session_path, alert: 'You are not authorized.'
       end
  end
end

class Administrators::UsersController < Administrators::BaseController

  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def show
  end

  def index
    @users = User.all
  end

  def new
     @user = User.new
  end

  def create
    @user = User.create(user_params)
    respond_with(:administrators, @user)
  end

  def edit
  end

  def update
    @user.update(user_params)
    respond_with(:administrators, @user)
  end

  def destroy
    @user.destroy
    respond_with(:administrators, @user)
  end

  private 

     def user_params
       params.require(:user).permit(:email, :password, :password_confirmation)
     end
end 

Instead you may want to focus on reusing the views through partials for example.

See: