How can I redirect a user's home (root) path based on their role using Devise?

后端 未结 5 2061
天涯浪人
天涯浪人 2020-12-02 11:18

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 authenticat

相关标签:
5条回答
  • 2020-12-02 11:54

    Blog post with the implementation http://minhajuddin.com/2011/10/24/how-to-change-the-rails-root-url-based-on-the-user-or-role/

    0 讨论(0)
  • 2020-12-02 11:57

    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.

    0 讨论(0)
  • 2020-12-02 11:58

    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'
    
    0 讨论(0)
  • 2020-12-02 12:01

    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.

    0 讨论(0)
  • 2020-12-02 12:21

    I do this in a Rails 3 app that uses Warden. Since Devise is built on top of Warden, I think it'll work for you, but be sure to experiment with it a bit before relying on it.

    class ProjectManagerChecker
      def self.matches?(request)
        request.env['warden'].user.role == 'project_manager'
      end
    end
    
    # routes.rb
    get  '/' => 'project_managers#index', :constraints => ProjectManagerChecker
    get  '/' => 'clients#index'
    

    If the user's role is "project_manager" the ProjectManagersController will be used - if it's not the ClientsController will be used. If they're not logged in at all, env['warden'].user will be nil and you'll get an error, so you'll probably want to work around that, but this will get you started.

    0 讨论(0)
提交回复
热议问题