Rails,Devise:相同的资源,基于用户类型的不同控制器

时间:2013-12-10 10:47:44

标签: ruby-on-rails devise routes

我有一个资源,比如Product,可以通过两个不同的用户类访问:比如CustomerAdmin。这两者之间没有继承。

我正在使用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

现在取决于谁登录(CustomerAdmin),我希望products_path指向相应的控制器。我希望避免使用customers_products_pathadmins_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}},这是不可行的。

2 个答案:

答案 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'