【问题标题】:Rails, Devise: Same resource, different controller based on user typeRails,设计:相同的资源,基于用户类型的不同控制器
【发布时间】:2013-12-10 10:47:43
【问题描述】:

我有一个资源,比如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,因为它是第一个定义的。

有什么线索吗?如果没有黑客攻击,我想做的事情可能根本不可能。

更新 按照the code的说法是不行的。

【问题讨论】:

    标签: ruby-on-rails devise routes


    【解决方案1】:

    事实证明,实现这一目标的最佳方法是使用路由约束:

    # 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
    

    我将约束对象存储在 helper 文件夹中,因为我真的不知道放置它们的最佳位置。

    感谢@crackofdusk 的提示。

    【讨论】:

      【解决方案2】:

      为此,您需要覆盖现有的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'
      

      【讨论】:

      • 感谢您的回答,但我希望该技巧适用于所有 Product 相关路径,而不仅仅是登录后的路径。这就是我确定路由范围的原因,即避免到处都有条件逻辑。
      • 你到底想要什么?...我没有得到你。
      • 我希望 Product 资源上的所有 CRUD 路径操作都指向不同的控制器,具体取决于登录的用户类别。
      • 那么你可以做一件事...在products controller 中添加一个前置过滤器并检查用户类型并采取相应措施。
      • 我想在路由级别执行此操作,因此是范围。不同的用户类,不同的控制器。否则ProductController 将变成一个巨大的意大利面碗。
      猜你喜欢
      • 2013-04-28
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      相关资源
      最近更新 更多