Topic: deeply nested form in rails 4.0 using cocoon


I am using ruby 2 with rails 4.0 and cocoon to created a deeply nested form. I have implemented several nested forms using cocoon already in the same application so the basics are covered.

I have a party model, a party has_many contact_mechanisms through party_contact_mechanism:

has_many :party_contact_mechanisms
has_many :contact_mechanisms, -> { uniq }, through: :party_contact_mechanisms
accepts_nested_attributes_for :party_contact_mechanisms, reject_if: :all_blank, allow_destroy: true

contact_mechanism has the reverse has_many through relationship and has_many :electronic_addresses:

has_many :party_contact_mechanisms
has_many :parties, -> { uniq }, through: :party_contact_mechanisms
has_many :electronic_addresses

accepts_nested_attributes_for :electronic_addresses,        reject_if: :all_blank, allow_destroy: true

To enable the nesting in the first place I have the accepts_nested_attributes_for call in both models for their respective child models.

electronic_addresses belongs to contact_mechanism:

belongs_to :contact_mechanism

I am permitting the nested attributes in my parties_controller:

def party_params
      params.require(:party).permit(party_contact_mechanisms_attributes: [
                                                      contact_mechanisms_attributes: [:id, :_destroy, :contact_mechanism_type_id,
                                                      electronic_addresses_attributes: [ :id, :_destroy, :electronic_address_string, :contact_mechanism_id]                                                    

What I am attempting to do is to add an electronic_address inside my party form:

= simple_form_for @party, :html => { :class => 'form-horizontal' } do |f|

  = f.error_notification
  -#-if @party.errors.present?
  -#  = @party.errors.full_messages.each do |msg|
  -#    %p= msg

    = controller.action_name.capitalize
          = link_to_add_association "Email", f, :party_contact_mechanisms,
          {:'data-association-insertion-node' => '#party_contact_mechanisms_email',
          :'data-association-insertion-method' => :append, force_non_association_create: true,
          partial: 'party_contact_mechanism_email_fields'}

        = f.simple_fields_for :party_contact_mechanisms do |pcm|
          = render 'party_contact_mechanism_email_fields', :f => pcm    

    = f.submit t(''), class: 'btn btn-primary btn-small'
    = link_to t('actions.back'),parties_path, class: 'btn btn-small'

my 'party_contact_mechanism_email_fields' partial lookslike this:

    = f.input :from_date, label: t('party_contact_mechanism.from_date')
    = f.input :thru_date, label: t('party_contact_mechanism.thru_date')

    = f.simple_fields_for :contact_mechanisms do |cm|

      = cm.simple_fields_for :electronic_addresses do |electronic_address|
        = render 'electronic_address_fields', :f => electronic_address

and then finally my 'electronic_address_fields' partial looks like this:

    = f.input :electronic_address_string, label: t('electronic_address.electronic_address_string')

When clicking the Email link, the form fields for the join model (party_contact_mechanism), and the input filed for electronic_address_string are shown. But when I save the form, the electronic_address_string value is not saved.

The params hash looks like this:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"pyT1zgKlRBJgtBC/LGCNEaOcsPZxlmc5zEO3xd/THlg=", "party"=>{"party_contact_mechanisms_attributes"=>{"1375196513291"=>{"from_date(1i)"=>"2013", "from_date(2i)"=>"7", "from_date(3i)"=>"30", "thru_date(1i)"=>"2013", "thru_date(2i)"=>"7", "thru_date(3i)"=>"30", "contact_mechanisms"=>{"electronic_addresses"=>{"electronic_address_string"=>""}}}}}, "commit"=>"Save"}

So instead of passing 'contact_mechanisms_attributes' and 'electronic_addresses_attributes', in both cases the "_attributes" is missing. So it seems to me, as I am not dynamically adding a nested form for contact_mechanisms and electronic_addresses their respective instances do not get build.

Can anyone offer any help to make this work?