Rails form_for路由模块未定义的方法

时间:2017-01-20 14:50:41

标签: ruby-on-rails ruby

我遇到了范围问题。 我已经定义了

# routes.rb
resources :asientos, module:'asientos'

# app/models/asientos/asiento.rb
module Asientos
  class Asiento < ActiveRecord:Base
  end
end


# app/controllers/asientos/asientos_controller.rb
module Asientos
  class AsientosController < ApplicationController
    def new
      @asiento = Asientos::Asiento.new
    end
  end
end

# app/views/asientos/asientos/new
<%= form_for(@asiento) do |f| %>
...

佣金路线

      asientos GET      /asientos(.:format)                                       asientos/asientos#index
               POST     /asientos(.:format)                                       asientos/asientos#create
   new_asiento GET      /asientos/new(.:format)                                   asientos/asientos#new
  edit_asiento GET      /asientos/:id/edit(.:format)                              asientos/asientos#edit
       asiento GET      /asientos/:id(.:format)                                   asientos/asientos#show
               PATCH    /asientos/:id(.:format)                                   asientos/asientos#update
               PUT      /asientos/:id(.:format)                                   asientos/asientos#update
               DELETE   /asientos/:id(.:format)                                   asientos/asientos#destroy

现在每当表单尝试渲染时,我都会

undefined method `asientos_asiento_index_path' for #<#<Class:0x000000065b3b40>:0x00000006ba5f30>

我见过一些像

这样的答案

form_for and scopes, rails 3

Module route in Rails with form_for(@object)

但是他们都没有提出明确的解决方案,或者建议进行某种修补。

此外,form_for现在生成asientos_前缀,并且在我的控制器中现在我还要将params.require(:asientos)重命名为params.require(:asientos_asientos)...不漂亮......

任何建议(除了撤消命名空间)都会非常感激。提前谢谢。

修改

似乎通过在模块定义中添加以下内容,路由按预期生成,没有“范围”

module Asientos
  def self.use_relative_model_naming?
    true
  end
...
end

但它仍然想要一个asientos_index_path ......“未定义的方法`asientos_index_path'”

2 个答案:

答案 0 :(得分:1)

好吧,在深入了解大量文章后,我找到了答案,并且有些帖子指出它与Inflections有关。 我的应用程序具有西班牙语的自定义变形,其中的变形看起来像:

Usuario -> Usuarios
Asiento -> Asientos
ItemAsiento -> ItemsAsiento

你会注意到它会使第一个单词复数化。话虽如此,从 rails / activemodel / lib / active_model / naming.rb 中提取的rails源代码中的以下代码显示了发生的内容

 def initialize(klass, namespace = nil, name = nil)
  @name = name || klass.name

  raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if @name.blank?

  @unnamespaced = @name.sub(/^#{namespace.name}::/, "") if namespace
  @klass        = klass
  @singular     = _singularize(@name)
  @plural       = ActiveSupport::Inflector.pluralize(@singular)
  @element      = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(@name))
  @human        = ActiveSupport::Inflector.humanize(@element)
  @collection   = ActiveSupport::Inflector.tableize(@name)
  @param_key    = (namespace ? _singularize(@unnamespaced) : @singular)
  @i18n_key     = @name.underscore.to_sym

  @route_key          = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural.dup)
  @singular_route_key = ActiveSupport::Inflector.singularize(@route_key)
  @route_key << "_index" if @plural == @singular
end

由于我的类在Asientos名称空间下,@ name变为Asientos :: Asiento,@ ununspaced =“Asiento”,@ xsular =“asientos_asiento”,@ popral =“asientos_asiento”,这里提出了问题。如果复数和单数都相等,则@route_key会后缀。

但为什么这些是平等的?由于西班牙语的变形使第一个单词多元化,并且它不知道名称空间,因此“asientos_asiento”被认为是复数(从变形的立场来看是真的,但由于第一部分是命名空间而不是模型名称,所以错误)。

我想这里的约定对我有用,因为对话似乎假设最后一部分始终是模型名称,因此英语复数将始终正常工作。 这不应该发生,因为rails已经检测到命名空间,它不应该依赖于@name本身,而是剥离命名空间,然后在没有命名空间的情况下单一化和复数化。

猴子补丁......我们走了......

感谢大家。

答案 1 :(得分:0)

您需要在form_for帮助器中指定模块/命名空间,如下所示:

<% form_for [:asientos, @asiento] do |f| %>