Rails form for not creating unique ids

77 views Asked by At

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

There are 2 answers

0
smathy On

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 }

2
Alex On

@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 %>