Блок области вложения Rails в ресурсах

Я пытаюсь создать путь, например product/:id/monthly/revenue/ и product/:id/monthly/items_sold, и эквивалентные именованные маршруты product_monthly_revenue и product_monthly_items_sold, и эти маршруты будут просто отображать диаграммы. Я попытался

resources :products do
    scope 'monthly' do
        match 'revenue', to: "charts#monthly_revenue", via: 'get'
        match 'items_sold', to: "charts#monthly_items_sold", via: 'get'
    end
end

Но это дает мне маршруты:

product_revenue    GET    /monthly/products/:product_id/revenue(.:format)    charts#monthly_revenue
product_items_sold GET    /monthly/products/:product_id/items_sold(.:format) charts#monthly_items_sold

где monthly вместо этого добавляется впереди, а именование маршрутов отключено. Я знаю, что мог бы просто сделать:

resources :products do
    match 'monthly/revenue', to: "charts#monthly_revenue", via: 'get', as: :monthly_revenue
    match 'monthly/items_sold', to: "charts#monthly_items_sold", via: 'get', as: :monthly_items_sold
end

но это не СУХОЕ, и это сходит с ума, когда я пытаюсь добавить больше категорий, например, ежегодно. Использование пространства имен заставит меня создавать новый контроллер для каждого пространства имен, когда я хочу объединить все диаграммы в один контроллер.

Итак, я предполагаю, что обобщенный вопрос будет таким: возможно ли создавать маршруты пространства имен без контроллеров пространства имен? Или можно закрепить создание категорий именованных маршрутов?

Изменить: использование

resources :products do
  scope "monthly", as: :monthly, path: "monthly" do
    match 'revenue', to: "charts#monthly_revenue", via: 'get'
    match 'items_sold', to: "charts#monthly_items_sold", via: 'get'
  end
end

дал бы мне маршруты

   monthly_product_revenue GET    /monthly/products/:product_id/revenue(.:format)    charts#monthly_revenue
monthly_product_items_sold GET    /monthly/products/:product_id/items_sold(.:format) charts#monthly_items_sold

что похоже на первый блок, неожиданно, потому что я ожидаю, что если область вложена в блок ресурсов, только маршруты в блоке области будут затронуты областью, а не блоком ресурсов.

Изменить 2: забыл включить эту информацию ранее, но я использую Rails 4.0.0 с Ruby 2.0.0-p247.


person Benedict Lee    schedule 24.10.2013    source источник


Ответы (2)


Вот как я мог бы подойти:

periods = %w(monthly yearly)
period_sections = %w(revenue items_sold)

resources :products do
  periods.each do |period|
    period_sections.each do |section|
      get "#{period}/#{section}", to: "charts##{period}_#{section}", as: "#{period}_#{section}"
    end
  end
end

Также можно использовать именованные маршруты и передавать значения в метод вашего контроллера через параметры (не забудьте правильно проверить перед использованием):

resources :products do
  get ":period/:section", to: "charts#generate_report", as: :report
end

# report_path(period: 'monthly', section: 'revenue')
person Damien Roche    schedule 24.10.2013
comment
Спасибо, это был хороший способ программно создавать маршруты. Иногда я забываю, что Rails по-прежнему остается Ruby, и забываю такие решения. Тем не менее, все еще странно, что scope в блоке resources влияет на блок ресурсов. Это ошибка? - person Benedict Lee; 24.10.2013
comment
@tempestfire2002 преуспевает в том, чтобы никогда не забывать, что Rails — это Ruby :) Я не думаю, что scope должен быть вложен в блок resource. Я не видел примеров этого. Для справки см. здесь: api.rubyonrails.org /classes/ActionDispatch/Routing/Mapper/. Я согласен, однако, я не ожидал результата, который вы получили. - person Damien Roche; 24.10.2013

Реальное решение - использовать nested:

resources :products do
  nested do
    scope 'monthly', as: :monthly do
      get 'revenue', to: 'charts#monthly_revenue'
      get 'items_sold', to: 'charts#monthly_items_sold'
    end
  end
end

Ссылка: https://github.com/rails/rails/issues/12626

person swalk    schedule 10.03.2015