'Prepopulate nested fields using Cocoon gem

I have an app with models we'll call Box, Stock, Experiment, & Sample. Here are what the ActiveRecord relationships look like:

class Box
  has_many :stocks
  accepts_nested_attributes_for :stocks
end

class Stock
  belongs_to :box
  has_many :samples
end

class Experiment
  has_many :samples
  accepts_nested_attributes_for :samples
end

class Sample
  belongs_to :experiment
  belongs_to :stock
end

I would like to have a button on my Box#show page, called "Generate Experiment From Box." Ideally, this will take me to my Experiment#new page, with prepopulated nested fields for Samples - one Sample per Stock. The Samples should not yet be saved objects as I want the user to be able to modify the samples before saving the Experiment. However, I am currently not able to get the nested fields to prepopulate.

app/views/boxes/show.html.erb

<%= link_to 'Generate New Experiment Box', new_experiment_path(box_id: @box.id) %>

app/controllers/experiments/experiments_controller.rb

def new
  if params[:box_id]
    stocks = Box.find(params[:box_id]).stocks
    samples_attributes = stocks.map { |stock| { stock_id: stock.id } }
    @experiment = Experiment.new(samples_attributes: samples_attributes)
  else
    @experiment = Experiment.new
  end
end

app/views/experiments/new.html.erb

<%= simple_form_for(@experiment) do |f| %>
  <div>
    #various form inputs
  </div>

  <div>
    <table>
      <thead>#column headers</thead>
      <tbody id="samples-table">
        <%= f.simple_fields_for :samples, f.object.samples.order(:id) do |sample_fields| %>
          <%= render 'sample_fields', f: sample_fields %>
        <% end %>        
      </tbody>
    </table>
    <div id="Links">
      <%= link_to_add_association "Add Samples to Experiment", f, :samples, :"data-association-insertion-node" => 'tbody#samples-table', :"data-association-insertion-method" => 'append' %>        
    </div>
  </div>
<% end %>

app/views/experiments/_sample_fields.html.erb

<tr class="nested-fields form-inline form-table-row">
  <td>#various text fields</td>
  <td>#various text fields</td>
</tr>

Any help is greatly appreciated! I've tried a few different approaches to this problem but still not able to get the nested fields to populate. Thanks!



Solution 1:[1]

If I understand correctly, when given a box, that has stocks, you want to create a new experiment with a sample for each stock from that box.

In your new action try the following:

def new
  @experiment = Experiment.new
  if params[:box_id]
    box = Box.find(params[:box_id])
    box.stocks.each do |stock|
      @expirement.samples.build(stock_id: stock.id) 
    end 
  end
end

Solution 2:[2]

I have tried the same and it works for me. I'm pasting my code here for reference.

@invoice = Invoice.new

template_mapping = TemplateMapping.find(1) # 1 is a static argument
template_mapping.template_mapping_details.each do |mapping|
 @invoice.invoice_items.build(item_id: mapping.item_id)
end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 nathanvda
Solution 2 MVP783