2011-01-20 2 views
22

Я работаю над приложением для управления проектами, и в приложении у меня есть project_managers и клиентов. Я использую Devise и CanCan для аутентификации/авторизации.Как я могу перенаправить путь пользователя (root) на основе их роли с помощью Devise?

В какой момент после входа в систему я должен перенаправлять пользователя на свой собственный контроллер/макет/представления? Есть ли способ проверить для current_user.role в routes.rb и установить корень (или перенаправить) в зависимости от того, являются ли они менеджером проекта или клиентом? Я могу изменить это в каком-нибудь проекте?

Заранее благодарим за любую помощь! --Mark

+0

Я задал аналогичный вопрос: http://stackoverflow.com/questions/3799393/rails-routes-root-with-nested-resource - ответ был создан для создания отдельного контроллера для домашней страницы, выполняющей маршрутизацию. Вы не можете получить доступ к этой информации об устройстве внутри маршрутов. Rb. – Skilldrick

ответ

32

Ваш routes.rb файл не будет представлять себе, какую роль у пользователя есть, поэтому вы не сможете использовать его для назначения определенных корневых маршрутов.

Что вы можете сделать, это настроить контроллер (например, passthrough_controller.rb), который, в свою очередь, может прочитать роль и перенаправить. Что-то вроде этого:

# 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' 

Таким образом, все пользователи будут иметь одну точку входа, которая, в свою очередь, перенаправляет их на соответствующий контроллер/действие в зависимости от их роли.

+0

Спасибо, человек, это полностью сработало. – Mark

+2

http://stackoverflow.com/questions/4753871/how-can-i-redirect-a-users-home-root-path-based-on-their-role-using-devise/4754097#4754097 - лучшая реализация , так как он не создает новый контроллер только для перенаправления. Кроме того, это приведет к 1 дополнительной поездке в оба конца от браузера к серверу каждый раз, когда пользователь перенаправляется на root_path. –

+0

Элегантное решение, которое не требует изменения какого-либо существующего кода, т. Е. Я могу хранить все инструкции redirect_to root_path, как и раньше. Мне это нравится :) – Wolfgang

6

Я делаю это в приложении Rails 3, которое использует Warden. Поскольку Devise построен поверх Warden, я думаю, что это сработает для вас, но обязательно экспериментируйте с ним немного, прежде чем полагаться на него.

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' 

Если роль пользователя является «project_manager» ProjectManagersController будет использоваться - если это не будет использоваться ClientsController. Если они вообще не вошли в систему, env['warden'].user будет nil, и вы получите сообщение об ошибке, так что вы, вероятно, захотите обойти это, но это поможет вам начать работу.

+0

Спасибо за ответ! Сначала я попробовал это, но я не мог заставить его работать (возможно, потому, что я новичок в этом). Не говоря уже о том, что я едва могу понять, что я делаю в этот момент, поэтому идея «экспериментировать с ним» страшно, как ад! – Mark

13

Самым простым решением является использование lambda:

root :to => 'project_managers#index', :constraints => lambda { |request| request.env['warden'].user.role == 'project_manager' } 
root :to => 'clients#index' 
+0

Это сработало для меня. У меня есть вопрос. Я использую Ruby 2.3.0, и это позволяет мне использовать новый сильный синтаксис лямбда. Но я получаю синтаксическую ошибку с 'ограничениями: -> {...}'. Он отлично работает, если я использую 'lambda' вместо' -> '. Есть идеи об этом? – artificis

10

Другой вариант, чтобы пройти процедурный к authenticated методу, как это (я использую rolify в этом пример):

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" 

Обратите внимание, что в Rails 4 вы имеют к specif y уникальное имя для каждого корневого маршрута, см. this issue.

+1

Это решение очень чистое с обновленным синтаксисом –

Смежные вопросы