Mel Mel - 9 months ago 79
Ruby Question

Rails - Cocoon Gem - populating foreign key id

I am trying to use simple form with cocoon gem to nest children forms inside a parent class form.

I have models for proposal and pitch.

The associations are:


has_one :pitch, inverse_of: :proposal
accepts_nested_attributes_for :pitch, reject_if: :all_blank, allow_destroy: true


belongs_to :proposal, inverse_of: :pitch

In my proposal form, I have:

<%= f.simple_fields_for :pitch do |f| %>
<%= f.error_notification %>
<%= render 'pitches/pitch_fields', f: f %>

<% end %>

<%= link_to_add_association 'Pitch', f, :pitch, partial: 'pitches/pitch_fields' %>

In my proposal controller, I have:

def new
@proposal =
# authorize @proposal

def edit
@proposal.build_pitch unless @proposal.pitch

def proposal_params
params.require(:proposal).permit(:title, :description,

pitch_attributes: [:id, :problem, :solution, :remark, :_destroy ])

pitches/_pitch_fields.html.erb has:

<div class="nested-fields">
<div class="form-inputs">
<%= f.input :problem, as: :text,
# :label => text_for_problem(current_user, @pitch.proposal),
:label => 'What issue does this proposal address?',
:input_html => {:rows => 10} %>

When I save all this and try it, the form loads and I can complete the form, but the foreign key for proposal_id saves as nil.

If I try to edit the form, I get an error that says:

Couldn't find Pitch with ID=5 for Proposal with ID=10

When I try:

NameError: undefined local variable or method `pitch' for main:Object

What do I need to do in order to force the proposal_id attribute in the pitch table to be set with the proposal id?

Answer Source

This is a bit weird, and imho a bug in rails, but the link_to_add_association will try to build a new pitch to be able to render it correctly. This will effectively delete the existing pitch.

So the solution is to add the option force_non_association_create: true on link_to_add_association. Or just drop the link_to_add_association altogether: why do you need it? You can have only one pitch, and you always create it if it does not exist?