JeffO
JeffO

Reputation: 137

How to create and submit a nested form with values populated from a has_many through association?

I would like to create a winnow_batch which has many bean_shipments through bean_winnow_batches.

 create_table "bean_shipments", force: :cascade do |t|
    t.string "lotcode", null: false
    t.decimal "weight_remaining_kg"
  end

  create_table "bean_winnow_batches", force: :cascade do |t|
    t.integer "bean_shipment_id"
    t.integer "winnow_batch_id"
    t.decimal "bean_shipment_weight_used_kg"
end

class BeanShipment < ApplicationRecord
  has_many :bean_winnow_batches
  has_many :winnow_batches, through: :bean_winnow_batches
  accepts_nested_attributes_for :bean_winnow_batches
end

class WinnowBatch < ApplicationRecord
  has_many :bean_winnow_batches
  has_many :bean_shipments, through: :bean_winnow_batches
  accepts_nested_attributes_for :bean_winnow_batches
end

class BeanWinnowBatch < ApplicationRecord
  belongs_to :bean_shipment
  belongs_to :winnow_batch
end

On the winnow_batch\new view, I want to show all of the bean_shipments that have bean_shipment.weight_remaining_kg < 0.

The user should be able to add multiple bean_shipments to the winnow_batch by entering a weight used.

My view should look like this:

<%= form_with(model: winnow_batch, local: true) do |form| %>
  <%= form.fields_for :bean_winnow_batches do |bwb| %>
     <table class="table1">
        <tr><th>Raw Beans in Inventory</th></tr>
        <tr>
          <td><i>Lot</td>
          <td><i>Weight in Iventory (kg)</td>
          <td><i>Weight Used in Winnow Batch (kg)</td>
        </tr>
        <tr>  
          <td><%= bwb.bean_shipment.lotcode %></td>
          <td><%= bwb.bean_shipment.weight_remaining_kg %></td>
          <td><%= bwb.text_field :bean_shipment_weight_used_kg %> </td>
          <%= bwb.hidden_field :bean_shipment_id, value: bwb.bean_shipment.id %>
        </tr>
      </table>
  <% end %>

winnow_batches_controller.rb

def new
    @winnow_batch = WinnowBatch.new
    @shipment_options = BeanShipment.where("weight_remaining_kg > ?", 0)
    
    @shipment_options.each do |ship|
        @winnow_batch.bean_winnow_batches.build(bean_shipment_id: ship.id)
    end
end

The error message I get on loading the winnow_batch/new view "undefined method 'bean_shipment' for #<ActionView::Helpers::FormBuilder:...)

How do I access the data in the has_many through association in the nested form, and how do I build the right number of nested objects and populate with the conditional data (weight < 0)?

Edit: I iterated through a query resultset to build the right number of objects with the correct data. But how can I display on the view the associated data in the bean_shipment?

Upvotes: 0

Views: 81

Answers (1)

Thomas Van Holder
Thomas Van Holder

Reputation: 1507

To address your question on the error:
"undefined method 'bean_shipment' for #<ActionView::Helpers::FormBuilder:...)

The issue occurs because you are calling the bean_shipment method on the the form builder.

 <%= form.fields_for :bean_winnow_batches do |bwb| %>

|bwb| refers to the form builder.
To access the object (beanwindowbatch), call .object on the form builder.

 <%= form.fields_for :bean_winnow_batches do |bwb_form| %>
...
  <tr>
    <td><%= bwb_form.object.bean_shipment.lotcode %></td>
  </tr>
...
 <% end %> 

Upvotes: 1

Related Questions