2011-01-20 37 views
22

Tôi đang làm việc trên ứng dụng quản lý dự án và trong ứng dụng, tôi có project_managerskhách hàng. Tôi đang sử dụng Devise và CanCan để xác thực/ủy quyền.Làm cách nào để chuyển hướng đường dẫn (root) của người dùng dựa trên vai trò của họ bằng Devise?

Tại thời điểm nào sau khi đăng nhập, tôi nên chuyển hướng người dùng đến bộ điều khiển/bố cục/chế độ xem cụ thể của riêng mình? Có cách nào để kiểm tra current_user.role trong routes.rb và đặt gốc (hoặc chuyển hướng) dựa trên việc họ có phải là người quản lý dự án hoặc khách hàng không? Đây có phải là một sự thay đổi mà tôi có thể thực hiện trong Devise ở đâu đó không?

Cảm ơn bạn đã giúp đỡ! --Mark

+0

Tôi đã hỏi một câu hỏi tương tự: http://stackoverflow.com/questions/3799393/rails-routes-root-with-nested-resource - câu trả lời là tạo một bộ điều khiển riêng cho trang chủ thực hiện định tuyến. Bạn không thể truy cập thông tin Devise đó bên trong routes.rb. – Skilldrick

Trả lời

32

Tệp routes.rb của bạn sẽ không biết bất kỳ vai trò nào người dùng có, do đó bạn sẽ không thể sử dụng nó để chỉ định các tuyến đường cụ thể.

Việc bạn có thể làm là thiết lập bộ điều khiển (ví dụ: passthrough_controller.rb) để có thể đọc vai trò và chuyển hướng. Một cái gì đó như thế này:

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

Bằng cách này, tất cả người dùng sẽ có một điểm vào, chuyển hướng họ đến bộ điều khiển/hành động phù hợp tùy thuộc vào vai trò của họ.

+0

Cảm ơn người đàn ông, điều này hoàn toàn làm việc. – Mark

+2

http://stackoverflow.com/questions/4753871/how-can-i-redirect-a-users-home-root-path-based-on-their-role-using-devise/4754097#4754097 là triển khai tốt hơn , vì nó không tạo ra một bộ điều khiển mới chỉ để chuyển hướng. Ngoài ra, điều này sẽ dẫn đến thêm 1 chuyến đi vòng từ trình duyệt đến máy chủ mỗi khi người dùng được chuyển hướng đến root_path –

+0

Giải pháp thanh lịch không yêu cầu thay đổi bất kỳ mã hiện có nào, tức là tôi có thể giữ tất cả các câu lệnh 'redirect_to root_path' như trước đây. Tôi thích nó :) – Wolfgang

6

Tôi làm điều này trong ứng dụng Rails 3 sử dụng Warden. Kể từ khi Devise được xây dựng trên đầu trang của Warden, tôi nghĩ rằng nó sẽ làm việc cho bạn, nhưng hãy chắc chắn để thử nghiệm với nó một chút trước khi dựa vào nó.

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' 

Nếu vai trò của người dùng là "project_manager", ProjectManagersController sẽ được sử dụng - nếu không phải là ClientsController sẽ được sử dụng. Nếu họ không đăng nhập ở tất cả, env['warden'].user sẽ là 0 và bạn sẽ gặp lỗi, vì vậy, có thể bạn sẽ muốn giải quyết vấn đề đó, nhưng điều này sẽ giúp bạn bắt đầu.

+0

Cảm ơn bạn đã trả lời! Tôi thực sự đã thử điều này trước, nhưng tôi không thể làm cho nó hoạt động (có lẽ vì tôi mới làm điều này). Chưa kể - Tôi chỉ có thể tìm ra những gì tôi đang làm vào thời điểm này, vì vậy ý ​​tưởng "thử nghiệm với nó" thật đáng sợ như địa ngục! – Mark

13

Giải pháp đơn giản nhất là sử dụng lambda:

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

Nó làm việc cho tôi. Tôi có một câu hỏi mặc dù. Tôi đang sử dụng Ruby 2.3.0 và nó cho phép tôi sử dụng cú pháp lambda stabby mới. Nhưng tôi nhận được lỗi cú pháp với 'ràng buộc: -> {...}'. Nó hoạt động tốt nếu tôi sử dụng 'lambda' thay vì' -> '. Bất kỳ ý tưởng về điều này? – artificis

10

Một lựa chọn khác là phải vượt qua một proc với phương pháp authenticated như thế này (tôi đang sử dụng rolify trong này ví dụ):

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" 

Lưu ý rằng trong Rails 4 bạn để tiết hoặc y một tên duy nhất cho mỗi tuyến đường gốc, xem this issue để biết chi tiết.

+1

giải pháp này rất sạch sẽ với cú pháp được cập nhật –

Các vấn đề liên quan