1

This is driving me crazy.

I have 2 models, StockShipment has_many Recipients.

It also has:

accepts_nested_attributes_for :recipients, reject_if: :all_blank, allow_destroy: true

I have this partial, that should create new rows for nested attributes with unique child_indexes

<%= form_with model: @stock_shipment do |form| %>
  <%= form.fields_for(:recipients, Recipient.new, child_index: Time.now.to_i) do |recipient_form| %>
    <%= turbo_stream.append('recipients-list', partial: 'shared/recipient_fields', locals: { form: recipient_form, new_record: true }) %>
  <% end %>
<% end %>

It's creating new rows in the form, but every attribute is the same:

name="[recipients][phone]"

Instead of:

name="[recipients][12234324][phone]"

EDIT

In my Stock Shipment action, I'm passing the form object like this:

    <tbody id="recipients-list">
      <%= form.fields_for :recipients do |recipient_form| %>
        <%= render 'shared/recipient_fields', form: recipient_form, locals: {user: current_user} %>
      <% end %>
    </tbody>
  </table>

  <%= link_to add_recipient_path(id: form.object),
              class: 'inline-block inline-flex items-center mt-5 text-black',
              id: 'add-new-recipient',
              data: { turbo_stream: true } do %>
              
    <span class="font-bold ml-3"><%= t('.add_recipient') %></span>
  <% end %>

My routes

get :add_recipient, to: "stock_shipments#add_recipient"

** My controller **

def add_recipient end

This is making only 1 record to be created instead of various records separately.

Please, can someone help?

I'm using Rails 7.

Thank you.

2 Answers 2

1

@stock_shipment is not set, so you're generating a form that is not linked to a model. Actual name attribute should look like this:

# v model                   child_index v (when :recipients is an association)
  stock_shipment[recipients_attributes][12234324][phone]
#    association ^          ^ accepts_nested_attributes

When you pass nil as a model, no magic is happening:

# v no model  v no child_index (not an association, you'd use :index in this case)
   [recipients][phone]
#   ^        `- no accepts_nested_attributes
#   `-literal argument for fields_for        

Since you don't need an actual <form> tag here, use fields helper instead of form_with:

<%= fields model: StockShipment.new do |f| %>
  <%= f.fields_for :recipients, Recipient.new, child_index: Time.now.to_i do |ff| %>
    #                          can only click once a second ^ just saying
    <%= turbo_stream.append(
      "recipients-list",
      partial: "shared/recipient_fields",
      locals: {form: ff, new_record: true})
      # maybe unnecessary ^ `form.object.new_record?`
    %>
  <% end %>
<% end %>
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Alex, indeed my @stockshipment is nil. The thing is, I'm building this nested forms from the StockShipment new action, so I'm passing the form object like this (edited question)
@user3074558 to clarify add_recipient_path(id: form.object) generates a url /stock_shipments/add_recipient?id=1 which will take you to StockShipments#add_recipient - you don't automatically get @stock_shipment there, you have to initialize it @stock_shipment = StockShipment.new, which will then be available in _add_recipient.turbo_stream.erb partial. also id param isn't really needed here.
0

It's been a while since I played with this but I'm fairly sure you need to pass a proc/lambda (something that responds to .call) like: -> { Time.now.to_i }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.