Search code examples
ruby-on-railsrubynested-formscocoon-gem

Rails, Cocoon Gem - undefined method `reflect_on_association' for NilClass:Class


I am trying to setup cocoon gem for nested forms in my Rails 5 app.

Im having a problem that others have posted about, but it seems the solutions that worked for them are not working for me.

I have models for address, organisation and settings. The associations are:

Address

belongs_to :addressable, :polymorphic => true, optional: true

Organisation

has_many :addresses, as: :addressable
        accepts_nested_attributes_for :addresses,  reject_if: :all_blank, allow_destroy: true

Settings

  has_many :addresses, as: :addressable
    accepts_nested_attributes_for :addresses,  reject_if: :all_blank, allow_destroy: true

My settings controller has:

def setting_params
      params.require(:setting).permit( :newsletter,
        addresses_attributes: [:id, :description, :unit, :building, :street_number, :street, :city, :region, :zip, :country, :time_zone, :latitude, :longitude, :_destroy]
       )
    end

My routes are:

resources :organisations do
    namespace :contacts do
    resources :addresses
    resources :phones 
    end
  end

resources :users, shallow: true do
    scope module: :users do
      resources :assign_roles
      resources :identities
      resources :org_requests
      resources :profiles
      resources :settings do 
        namespace :contacts do
          resources :addresses
          resources :phones 
        end
      end 
    end

My address form has:

My settings form has:

<%= simple_form_for [@user, @setting] do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :newsletter, as: :radio_buttons, label: "Subscribe to our newsletter" %>

    <%= simple_fields_for :addresses do |f| %>
            <%= f.error_notification %>
                <%= render 'contacts/addresses/address_fields', f: f %>
            <%= link_to_add_association 'Manage address', f, :addresses, partial: 'contacts/addresses/address_fields' %>    
        <% end %>   
  </div>
<% end %>  

The error says:

undefined method `reflect_on_association' for NilClass:Class

This line is highlighted in the error message:

                <%= link_to_add_association 'Manage address', f, :addresses, partial: 'contacts/addresses/address_fields' %>        

For others the problem has been using the singular instead of the plural; or using @addresses instead of :addresses (although some of the solutions have suggested its supposed to be @ instead of :.

I have tried each of these in each combination.

Can anyone see what I need to do to set this up?

TAKING EDMUND'S SUGGESTION

I can see from the simple form documentation that nested attributes should be handled differently in the forms.

https://github.com/plataformatec/simple_form/wiki/Nested-Models#example-for-strong-parameters

I tried changing the form to:

<%= simple_fields_for "addresses_attributes[]", address do |f| %>

That doesnt work either. I can't render a page to inspect.

The error line in this context points to a problem with the new action in my organisation controller. That has:

 def new
    @organisation = Organisation.new
    @organisation.addresses_build
  end

The error message says:

undefined method `addresses_build' for #<Organisation:0x007fcf6ff25f08>
Did you mean?  addresses

I now wonder if I need to build address_attributes instead of address. But when I try I get an error that says:

undefined method `addresses_attributes_build' for #<Organisation:0x007fcf72c26d68>
Did you mean?  addresses_attributes=

Solution

  • You have to write

    f.simple_fields_for :addresses 
    

    The f refers to the form, and you need this to be able to iterate over all child-addresses.

    And secondly, it is better to have the link_to_add_association outside of the loop (otherwise you can only add a new address if there already is one?)

    So write something like

    <%= f.simple_fields_for :addresses do |f| %>
      <%= render 'contacts/addresses/address_fields', f: f %>
    <% end %>  
    <%= link_to_add_association 'Manage address', f, :addresses, partial: 'contacts/addresses/address_fields' %>    
    

    (imho the example you refer to in the simple-form documentation is outdated and the elaborate form is not needed)