2

I am trying to make an app with Rails 4.

I use simple form gem for forms and am trying to use Cocoon gem for nested elements of the forms.

I asked this question, which explains what I'm trying to achieve in more detail: Rails - Multiple entries for a single attribute

I have a profile model and a qualifications model. The associations are:

profile.rb

has_many :qualifications  
    accepts_nested_attributes_for :qualifications,  reject_if: :all_blank, allow_destroy: true

qualification.rb

belongs_to :profile

the profiles controller includes the qualification attributes in the strong params:

def profile_params
      params[:profile].permit(:user_id, :title, :hero, :overview, :research_interest, :occupation, :external_profile, 
        :working_languages, :tag_list,
          qualifications_attributes: [:id, :level, :title, :year_earned, :institution, :_destroy] )
    end

My profile form now has:

 <div class="intpol2">
              Your qualifications
            </div>

              <%= render 'qualifications/qualification_fields', f: f %>  

          </div>
          <div class="row">
            <div class="col-md-6">
              <%= link_to_add_association 'Add a qualification', f: f,  partial: 'qualifications/qualification_fields' %>

            </div>

My qualifications partial form is now named in my qualification views folder as _qualifications_fields.html.erb

<div class="nested-fields">
<div class="container-fluid">

        <%= simple_fields_for :qualifications do |f| %>

          <div class="form-inputs">


            <div class="row">
                <div class="col-md-6">
                    <%= f.input :title, :label => "Your award" %> 
                </div>

                <div class="col-md-6">


                </div>


            </div>

            <div class="row">
                <div class="col-md-6">
                    <%= f.input :level,   collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
                </div>


                <div class="col-md-6">
                <%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year) %>
                </div>

          </div>


          <div class="row">
                <div class="col-md-6">
                     <!-- link_to_remove_association 'Remove this qualification', f, :f  -->
                </div>

          </div>


          </div>
        <% end %>
</div>  
</div>      

I commented out the remove link, because as is, I get this error:

undefined method `new_record?' for nil:NilClass

I'm baffled by the way Rails reports errors- I rarely understand error messages of this style, but I gather it's something to do with there not being any qualifications to remove. Does cocoon handle this?

When I comment this out and try again, I get this error with the link to add an association:

undefined method `object' for #<Hash:0x007fe70c501ea0>

I don't know what this message means either.

So, by following the steps in the Cocoon gem docs, (with changes because I don't know how to write things in haml; and changing the form of expression to reference the form builder 'f: f' works across the rest of my forms, so Im guessing that the expression shown in the docs might be something to do with haml), I have 2 errors at this stage:

  1. add association - undefined method object
  2. remove association - undefined method `new_record?

I'm struggling to understand what's going on here.

TAKING JEIWAN'S SUGGESTION:

I change my profile form to:

    <%= simple_form_for @profile, html: { multipart: true }  do |f| %>
            <%= f.error_notification %>

              <div class="form-inputs">


          <div class="row">

            <div class="intpol2">
              Your professional qualifications
            </div>
            <%= simple_fields_for :qualifications do |f| %>

              <%= render 'qualifications/qualification_fields', f: f %>  

            </div>
          <div class="row">
            <div class="col-md-6">

               <%= link_to_add_association 'Add a qualification', f, :qualifications, partial: 'qualifications/qualification_fields' %>
            <% end %>
            </div>

          </div>

              <div class="form-actions">
                <%= f.button :submit, "Submit", :class => 'formsubmit' %>
              </div>
        <% end %>
    </div>
  </div>    
</div>      

I change my qualification fields form to:

<div class="nested-fields">
<div class="container-fluid">

          <div class="form-inputs">
    <div class="row">
                <div class="col-md-6">
                    <%= f.input :title, :label => "Your award" %> 
                </div>

                <div class="col-md-6">


                </div>


            </div>

            <div class="row">
                <div class="col-md-6">
                    <%= f.input :level,   collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
                </div>


                <div class="col-md-6">
                <%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year) %>
                </div>

          </div>


          <div class="row">
                <div class="col-md-6">
                    <%= link_to_remove_association 'Remove this qualification', f %>
                </div>

          </div>


          </div>

</div>  
</div>      

When I save this and try again, I get this error:

undefined method `new_record?' for nil:NilClass

The error message highlights this line:

            <%= link_to_remove_association 'Remove this qualification', f %>
Community
  • 1
  • 1
Mel
  • 2,481
  • 26
  • 113
  • 273

1 Answers1

2
link_to_add_association 'Add a qualification', f: f,  partial: 'qualifications/qualification_fields'

f: f is incorrect here. The second parameter should be a form builder (just an object, not a hash) and the third parameter – the name of the association, i.e. :qualifications in your case. So it should look like this:

link_to_add_association 'Add a qualification', f, :qualifications, partial: 'qualifications/qualification_fields'

And here:

link_to_remove_association 'Remove this qualification', f, :f

:f is also wrong. Third parameter here is HTML options. If you don't need them, then just specify 2 parameters:

link_to_remove_association 'Remove this qualification', f

Next, _qualification_fields.html.erb shouldn't contain simple_fields_for. This partial is used to render the fields of one distinct association object. It is shown when you click 'Add a qualification' or when your parent object already has some qualifications. simple_fields_for :qualifications should be put in you profile form and contain render 'qualifications/qualifications_fields', f: f and link_to_add_association .... Consider this example: https://github.com/nathanvda/cocoon#simpleform

Jeiwan
  • 954
  • 6
  • 13
  • Hi - I tried this, but get the same errors. Output pasted above. – Mel Dec 31 '15 at 05:10
  • Just fyi, I also tried moving the " ' " to after the f: f as you showed, but I get this error when I try that: The partial name (qualifications/qualification_fields, f: f) is not a valid Ruby identifier; make sure your partial name starts with underscore, and is followed by any combination of letters, numbers and underscores. – Mel Dec 31 '15 at 05:15
  • Sorry, that was a typo, the quote shouldn't be moved. Here's another issue in your code: `simple_fields_for` should be `f.simple_fields_for`. This should solve the error with `undefined method 'new_record?'`. – Jeiwan Dec 31 '15 at 05:22
  • Thanks for that. When I try that, the profile form loads, but skips over the qualifications form partial and the link to add a new qualification. It just goes from the qualifications heading to the next heading in the next segment of the form. – Mel Dec 31 '15 at 05:27
  • It happens because profile has no qualifications, so no fields displayed. You need to call `@profile.qualifications.build` in the controller action, in this case profile will always have an empty and not persisted qualification. – Jeiwan Dec 31 '15 at 05:37
  • I would expect that in the show page, but not the form. That's what's happening in the form itself. No form fields are displayed in the profile form for the qualification fields. I have this in my profiles controller: @profile.qualifications.build – Mel Dec 31 '15 at 05:40
  • Could the problem be something to do with the update function needing some permission to access the field. The link should at least show even if there are no qualifications when the profile was created – Mel Dec 31 '15 at 05:57
  • Wait. I found it - the < end > tag was after the link. Moved it above the link and now works. Thanks very much for your help – Mel Dec 31 '15 at 05:59