Rails может решить эту проблему путем создания вложенного ресурса :
resources :categories do
resources :products, shallow: true
end
Это вложит маршруты сбора, чтобы вы получили GET /categories/:category_id/products
.
Хотя он может быть не таким коротким, как ваши маршруты тщеславия, он гораздо более универсален, поскольку позволит вам показывать продукты для любой потенциальной категории, не разбираясь в кодовой базе.
Вы бы настроили контроллер следующим образом:
class ProductsController < ApplicationController
before_action :set_category, only: [:new, :index, :create]
# GET /categories/:category_id/products
def index
@products = @category.products
end
# GET /categories/:category_id/products/new
def new
@product = @category.products.new
end
# POST /categories/:category_id/products
def new
@product = @category.products.new(product_params)
# ...
end
# ...
private
def set_category
@category = MainCategory.includes(:products)
.find_by!('id = :x OR name = :x', x: params[:id])
end
end
Вы можете ссылаться на продукты любой категории, используя category_products_path
именованный помощник пути:
link_to "#{@category.name} products", category_products_path(category: @category)
Вы также можете использовать полиморфные помощники пути :
link_to "#{@category.name} products", [@category, :products]
form_for [@category, @product]
redirect_to [@category, :products]
Если вы хотите направить невыпущенные GET /products
и вложенные GET /categories/:category_id/products
на разные контроллеры, хитрый трюк заключается в использовании опции модуля:
resources :products
resources :categories do
resources :products, only: [:new, :index, :create], module: :categories
end
Это будет маршрутизировать вложенные маршрутыдо Categories::ProductsController
.