0

我正在使用 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>

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

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

4

2 回答 2

1

问题是这条线

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

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

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

然后你可以写:

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

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

够清楚吗?

于 2019-08-06T19:11:23.463 回答
0

我认为这是因为您的表单适用于 amonitor_category并且 url 指向create_monitor_category_path. 但是你向我们展示了OidController. 你需要类似的东西:

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

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

于 2019-08-06T10:39:19.233 回答