How can I redirect a user's home (root) path based on their role using Devise?
I'm working on a project management app, and in the app, I have project_managers and clients. I'm using Devise and CanCan for authentication/authorization.
At what point after login should I be redirecting the user to their own specific controller/layout/views? Is there a way to check for current_user.role
in routes.rb
and set the root (or redirect) based on whether or not they're a project manager or a client? Is this a change I can make in Devise somewhere?
Thanks in advance for any help! --Mark
Your routes.rb
file won't have any idea what role the user has, so you won't be able to use it to assign specific root routes.
What you can do is set up a controller (for example, passthrough_controller.rb
) which in turn can read the role and redirect. Something like this:
# passthrough_controller.rb
class PassthroughController < ApplicationController
def index
path = case current_user.role
when 'project_manager'
some_path
when 'client'
some_other_path
else
# If you want to raise an exception or have a default root for users without roles
end
redirect_to path
end
end
# routes.rb
root :to => 'passthrough#index'
This way, all users will have one point of entry, which in turn redirects them to the appropriate controller/action depending on their role.
Another option is to pass a proc to the authenticated
method like this (I'm using rolify in this example):
authenticated :user, ->(u) { u.has_role?(:manager) } do
root to: "managers#index", as: :manager_root
end
authenticated :user, ->(u) { u.has_role?(:employee) } do
root to: "employees#index", as: :employee_root
end
root to: "landing_page#index"
Note that in Rails 4 you have to specify a unique name for each root route, see this issue for details.
The simplest solution is to use lambda
:
root :to => 'project_managers#index', :constraints => lambda { |request| request.env['warden'].user.role == 'project_manager' }
root :to => 'clients#index'