rails - 如何为嵌套资源路由定位嵌套控制器

时间:2017-05-04 09:51:09

标签: ruby-on-rails routes

routes.rb我有

namespace :admin do
  resources :clients do, only: [:index] do
    resources :products, only: [:index, :new, :create]
  end

  resources :products, only: [:index]
end

请注意,resources :products有两行。一个嵌套在resources :clients内,另一个嵌套在:admin上的顶级资源中;这两者中的每一个在应用程序中都有不同的目的。

rake routes给了我:

           admin_clients GET  /admin/clients(.:format)                         admin/clients#index
   admin_client_products GET  /admin/clients/:client_id/products(.:format)     admin/products#index
                         POST /admin/clients/:client_id/products(.:format)     admin/products#create
new_admin_client_product GET  /admin/clients/:client_id/products/new(.:format) admin/products#new
          admin_products GET  /admin/products(.:format)                        admin/products#index                    

我有一个admin_client_products嵌套product#index资源。对于顶级admin_products资源,我也有product#index。但是,它们指向相同的控制器操作:admin/product#index

问题:此时,我需要rails来推断这些是两种不同的行为。使用rails约定,有没有办法告诉rails这两个资源应该有不同的控制器操作,即一个应该点击admin/products#index而另一个应该点击admin/clients/products#index

嵌套路线应该点击:

class Admin::Clients::ProductsController < Admin::BaseController      
  def index; end
end

顶级路线应该是这样的:

class Admin::ProductsController < Admin::BaseController      
  def index; end
end

1 个答案:

答案 0 :(得分:1)

绝对可以!

在这里,您需要通过显式指定用于资源的控制器来自定义资源路由。 :controller选项可以让您这样做。

因此,在您的情况下,为clients/products资源指定控制器admin_clients_products将以您想要的方式工作。

namespace :admin do
  resources :clients, only: [:index] do
    resources :products, only: [:index, :new, :create], controller: 'clients/products'
  end                                                 # ------------------------------

  resources :products, only: [:index]
end

rails routes现在可以为您提供所需内容:

admin_client_products    GET /admin/clients/:client_id/products(.:format)   admin/clients/products#index
                         POST   /admin/clients/:client_id/products(.:format)     admin/clients/products#create
new_admin_client_product GET    /admin/clients/:client_id/products/new(.:format) admin/clients/products#new
admin_clients            GET    /admin/clients(.:format)                         admin/clients#index
admin_products           GET    /admin/products(.:format)                        admin/products#index

=========================

额外位:

如果您想省略网址中的/admin部分(我的意思是,如果您的应用程序的路由设计允许),那么您可以使用:

scope module: 'admin' do...end
以下内容:

scope module: 'admin' do
  resources :clients, only: [:index] do
    resources :products, only: [:index, :new, :create], controller: 'clients/products'
  end

  resources :products, only: [:index]
end

突然你的路线开始看起来很棒:)

client_products     GET    /clients/:client_id/products(.:format)     admin/clients/products#index
                    POST   /clients/:client_id/products(.:format)     admin/clients/products#create
new_client_product  GET    /clients/:client_id/products/new(.:format) admin/clients/products#new
clients             GET    /clients(.:format)    admin/clients#index
products            GET    /products(.:format)  admin/products#index