JuanMartinez
JuanMartinez

Reputation: 29

Dynamic Forms with Cocoon - undefined method `reflect_on_association' for NilClass:Class:

im using the cocoon gem to build some dynamic form in which i can add new text fields. Ive read others people same problem but i dont know what im doing wrong, i know it has to be something with the associations but i dont seem to get it.

So these are my models:

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

And my form:

<%= 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>

with the partial _oids_fields.html.erb:

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

What am i doing wrong? Im getting undefined method `reflect_on_association' for NilClass:Class:. Form is okay since i was looking at the page of cocoon and is the same syntax, so i guess it must be something with the associations but i dont really know, im kind of new to the rails world. Maybe since it says nilClass, i need to create a controller for the Oid model in which i make a new method or something? im lost.

Apparently this doesnt work either, i have the same error:

class OidController < ApplicationController

  def new
    @oid = Oid.new
  end

end  

thank you for every answer.

edit: just to be more clear, because im very confused.

Before trying to implement this dynamic form, i already have a form which is working correctly. For example, last two fields are these:

      <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>

So basically here im storing the values entered on the attribute :oid and :oid2 from the model .

but instead of having these two fields, i want to have only one, and add more dynamically, so i can enter for example 6 values and saved them all on the :oids attribute. Since i was saving the valued on an attribute, i dont know if i have to create a model for Oid, like a did before, and make it belong_to monitor_category. Or if i can just add an attribute :oids to the controller and store all the values in that variable.

Upvotes: 0

Views: 199

Answers (2)

nathanvda
nathanvda

Reputation: 50057

The problem is this line

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

This creates a form for a MonitorCategory but does not set an object. So when you then call f.simple_fields_for there is no object to iterate over the associations.

Normally in the controller you set a @monitor_category instance variable, which is either set to an existing instance (when editing) or a newly created item.

And then you can write:

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

Rails is smart enough to deduce the url from the object, it will either create a new one or update an existing one.

Is that clear enough?

Upvotes: 1

I think it's because your form is for a monitor_category and the url is pointing to the create_monitor_category_path. But you're showing us the OidController. You would need something like:

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

This will initialize the parent object and then build the child association. You need to build at least one child for the fields to show up when using fields for.

Upvotes: 0

Related Questions