我有一个资源,比如Product
,可以通过两个不同的用户类访问:比如Customer
和Admin
。这两者之间没有继承。
我正在使用Devise进行身份验证:
# config/routes.rb
devises_for :customers
deviser_for :admins
我有这两个控制器:
# app/controllers/customers/products_controller.rb
class Customers::ProductsController < ApplicationController
和
# app/controllers/admins/products_controller.rb
class Admins::ProductsController < ApplicationController
现在取决于谁登录(Customer
或Admin
),我希望products_path
指向相应的控制器。我希望避免使用customers_products_path
和admins_products_path
,这很麻烦。
所以我已经设置了我的路线
# config/routes.rb
devise_scope :admin do
resources :products, module: 'admins'
end
devise_scope :customer do
resources :products, module: 'customers'
end
这不起作用。当我以Customer
身份登录时,products_path
仍然指向Admins::ProductsController#index
,因为它是第一个定义的。
有任何线索吗?如果没有黑客行为,我想要做的事情可能是不可能的。
更新 根据{{3}},这是不可行的。
答案 0 :(得分:2)
事实证明,实现这一目标的最佳方法是使用路由约束:
# config/routes.rb
resources :products, module: 'customers', constraints: CustomersConstraint.new
resources :products, module: 'admins', constraints: AdminsConstraint.new
# app/helpers/customers_constraint.rb
class CustomersConstraint
def matches? request
!!request.env["warden"].user(:customer)
end
end
# app/helpers/admins_constraint.rb
class AdminsConstraint
def matches? request
!!request.env["warden"].user(:admin)
end
end
我将约束对象存储在帮助文件夹中,因为我真的不知道放置它们的最佳位置。
感谢@crackofdusk提示。
答案 1 :(得分:1)
为此,您需要覆盖现有的after_sign_in_path_for设计方法。把它放在app/controllers/application_controller.rb
def after_sign_in_path_for(resource)
if resource.class == Admin
'/your/path/for/admins'
elsif resource.class == Customer
'/your/path/for/customers'
end
end
注意:如果您要实施用户请求的previous_url
,那么您可以像这样使用它:
session[:previous_url] || 'your/path/for/admins'