具有相同命名空间的嵌套控制器的隐式路由

时间:2015-04-29 08:37:38

标签: ruby-on-rails ruby-on-rails-4 routes nested-routes

鉴于Rails 4.1,两个控制器CRM::CompaniesControllerCRM::ContactPeople,两个模型CRM::CompanyCRM::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) 
# ...

但是,对URL帮助程序使用Array方法

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

尝试生成每个资源命名空间的URL:

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

我想要&#34; crm&#34;在我的路径中只在开头一次(除非它打破了常见的Rails方法)并且明确地将URL添加到每个表单将是很难看的。有什么我可以做的(可能在路由,模型或第一个form_for参数),以便Rails知道如何构建正确的路径?或者是否有更多类似Rails的方法来生成这种结构,以便Rails自动知道如何构建路径?

2 个答案:

答案 0 :(得分:1)

您需要在调用form_for

时添加名称空间

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

此外,由于您正在使用命名空间模型,因此需要在它们上定义以下类方法(from rails/rails issue #10705)以忽略命名空间:

def self.use_relative_model_naming?
  true
end

答案 1 :(得分:0)

我尝试了几种方法来为我找到最烦人的方法。我首先要改变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_for @crm_company
= url_for [@crm_company, @crm_contact_person]

但是如果CRM :: ContactPerson是浅层嵌套并且作为CRM的子项出现并直接作为CRM的孩子,那么上面的问题会重新出现:

= url_for @crm_contact_person
# undefined method `contact_person_path'

在这种情况下,我们可以将嵌套和未嵌套的部分拆分为CRM :: Companies :: ContactPerson和CRM :: ContactPerson,并使用CRM :: Companies模块的相对模型命名。但是,这似乎是很多开销,甚至可能比使用显式URL帮助程序更糟糕。

所以现在我找不到一个全面的解决方案,但至少只有嵌套资源的解决方案才能正常工作。