动态表单与 Cocoon - 未定义的方法 'reflect_on_association' for NilClass:Class:



im 使用 cocoon gem 构建一些动态表单,我可以在其中添加新的文本字段。我读过其他人同样的问题,但我不知道我做错了什么,我知道它一定是联想有关,但我似乎不明白。

所以这些是我的模型:

class MonitorCategory < ActiveRecord::Base
  validates :operation, presence: true
  attr_accessor :oid, :oid2, :oids, :snmp_oper, :custom_tab_name, :custom_tab_unit, :redfish, :ipmi
  has_many :oids
  has_and_belongs_to_many :sensors
  accepts_nested_attributes_for :oids
class Oid < ActiveRecord::Base
  belongs_to :monitor_category
 end

和我的表格:

<%= simple_form_for(:monitor_category, url: create_monitor_category_path, :html => { :remote => true, :method => :post }) do |f| %>
<div id='oids'>
    <%= f.simple_fields_for :oids do |oid| %>
    <%= render 'oids_fields', :f => oid %>
    <% end %>
    <div class='links'>
      <%= link_to_add_association 'add oid', f, :oids %>
    </div>
</div>

使用部分 _oids_fields.html.erb:

<div class='nested-fields'>
<%= f.input :oids %>
</div>

我做错了什么? 我正在为 NilClass:Class: 获取未定义的方法"reflect_on_association"。 形式还可以,因为我正在查看 cocoon 的页面并且是相同的语法,所以我想它一定是与关联有关的东西,但我真的不知道,我对 rails 世界有点陌生。也许既然它说 nilClass,我需要为 Oid 模型创建一个控制器,在其中我制作一个新方法或其他东西?我输了。

显然这也不起作用,我有同样的错误:

class OidController < ApplicationController
  def new
    @oid = Oid.new
  end
end  

谢谢你的每一个回答。

编辑:只是为了更清楚,因为我非常困惑。

在尝试实现此动态表单之前,我已经有一个正常工作的表单。例如,最后两个字段是:

      <div class="col-md-12">
        <%= f.input :oid, label: 'SNMP OID', as: :search, placeholder: 'Output stored in var1.', required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
      </div>
      <div class="col-md-12">
        <%= f.input :oid2, label: 'SNMP OID 2', as: :search, placeholder: 'Output stored in var2.', required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
      </div>

所以基本上在这里 im 存储从模型中输入的属性 :oid 和 :oid2 的值。

但是,我不想拥有这两个字段,而是只想拥有一个字段,并动态添加更多字段,因此我可以输入例如 6 个值并将它们全部保存在 :oids 属性上。由于我正在将值保存在属性上,因此我不知道我是否必须像以前那样为 Oid 创建一个模型并使其belong_to monitor_category。或者,如果我可以将属性:oids添加到控制器并将所有值存储在该变量中。

问题是这一行

simple_form_for(:monitor_category, url: create_monitor_category_path, :html => { :remote => true, :method => :post }) do |f| 

这将为MonitorCategory创建一个表单,但不设置对象。因此,当您调用f.simple_fields_for时,没有对象可以迭代关联。

通常在控制器中设置一个@monitor_category实例变量,该变量设置为现有实例(编辑时(或新创建的项目。

然后你可以写:

simple_form_for(@monitor_category, :html => { :remote => true, :method => :post }) do |f| 

Rails足够聪明,可以从对象中推断出url,它将创建一个新的网址或更新一个现有的网址。

这够清楚吗?

我认为这是因为您的表单是用于monitor_category并且 url 指向create_monitor_category_path .但是你向我们展示了OidController.您需要类似以下内容:

class MonitorCategoryController < ApplicationController
  def new
    @monitor_category = MonitorCategory.new
    @monitor_category.oids.build
  end
end

这将初始化父对象,然后构建子关联。您需要构建至少一个子项,以便在使用字段时显示字段。