Неявная маршрутизация для вложенных контроллеров с одинаковым пространством имен

Учитывая Rails 4.1, два контроллера CRM::CompaniesController и CRM::ContactPeople, две модели CRM::Company и CRM::ContactPerson и следующие маршруты:

namespace :crm do
  resources :companies do
    resources :contact_people
  end
end

Сгенерированные помощники URL содержат пространство имен CRM только один раз, и это именно то, что я хочу:

crm_company_contact_people      GET  /crm/companies/:company_id/contact_people(.:format)
new_crm_company_contact_person  GET  /crm/companies/:company_id/contact_people/new(.:format) 
# ...

Однако использование подхода Array для помощников URL

= form_for([@crm_company, @crm_contact_person]) do |f|

пытается сгенерировать URL-адрес с каждым ресурсом в пространстве имен:

undefined method `crm_company_crm_contact_people_path' for #<#<Class...

Я хотел бы иметь «crm» в своих путях только один раз в начале (если это не нарушает общий подход Rails), и было бы некрасиво явно добавлять URL-адрес в каждую форму. Есть ли что-то, что я могу сделать (возможно, в маршрутах, модели или первом аргументе form_for), чтобы Rails знал, как построить правильный путь? Или есть более похожий на Rails способ создания такой структуры, чтобы Rails автоматически знал, как строить пути?


person Sebastian vom Meer    schedule 29.04.2015    source источник
comment
обратитесь к этому stackoverflow.com/questions/2718059/   -  person amtest    schedule 29.04.2015
comment
Спасибо, проблема та же. Но, похоже, ОП искал конкретное решение для form_for (в данном случае form_for(@foo, url: ...). Я пытаюсь найти Rails-Way, чтобы избежать этого обходного пути, поэтому приветствуются более общие изменения структуры маршрута или других элементов.   -  person Sebastian vom Meer    schedule 29.04.2015


Ответы (2)


Вам нужно включить пространство имен в свой вызов form_for:

= form_for([:crm, @crm_company, @crm_contact_person]) do |f|

Кроме того, поскольку вы используете модели с пространством имен, вам необходимо определить для них следующий метод класса (из рельсов /rails issue #10705), чтобы игнорировать пространство имен:

def self.use_relative_model_naming?
  true
end
person fylooi    schedule 29.04.2015
comment
К сожалению, это добавляет пространство имен в начале и сохраняет пространства имен моделей: crm_crm_company_crm_contact_person_path - person Sebastian vom Meer; 30.04.2015
comment
Ах, забыл о моделях с именами. Отредактировано, чтобы позаботиться об этом. - person fylooi; 30.04.2015
comment
Спасибо. После отладки url_for я наткнулся на ActiveModel::Naming и .use_relative_model_naming? тоже. Я все еще думаю о способах его без добавления чего-то к form_for. Однако, похоже, это правильный подход. - person Sebastian vom Meer; 02.05.2015

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

module CRM
  def self.use_relative_model_naming?
    true
  end
end

Однако при этом пространство имен удаляется из каждого объекта, включая компанию. Итак, следующее больше не работает:

= url_for @crm_company
# undefined method `company_path'

Чтобы избежать этого, я попытался удалить пространство имен только для определенных моделей, изменив имя модели (обратите внимание, что это имеет больше побочных эффектов, чем генерация URL):

class CRM::ContactPerson < ActiveRecord::Base
  def self.model_name
    ActiveModel::Name.new(self, CRM)
  end
end

Теперь следующие URL-адреса работают нормально:

= url_for @crm_company
= url_for [@crm_company, @crm_contact_person]

Но если CRM::ContactPerson имеет неглубокую вложенность и отображается как дочерний элемент CRM::Company И как дочерний элемент CRM, проблема появляется снова:

= url_for @crm_contact_person
# undefined method `contact_person_path'

В этом случае мы могли бы разделить вложенную и невложенную часть на CRM::Companies::ContactPerson и CRM::ContactPerson и использовать относительное наименование модели для модуля CRM::Companies. Однако это кажется слишком накладным и может быть даже хуже, чем использование явных помощников URL.

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

person Sebastian vom Meer    schedule 05.05.2015