Create Multiple Records For Model from One Form & One Submit Button Click

Hi there,

I’m fairly new to Rails. I’m working on a rather large project and I’m stuck on a certain part. I’m building an event platform that handles everything from registration to scoring. The registration part is where I’m stuck.

Some background:

  • My models are User (using devise), Register, Show, Event, Division
  • Each Show has many Events and each Event has many Divisions declared when creating the Show.
  • User creates profile and then can see multiple Shows they can choose from to register for.
  • User clicks the show name and is taken to a registration form (on the Register model) where they can choose which events they want to register for by declaring the Division and Horse Name for each event they plan on participating in.

The problem I’m running into is I’m trying to get each division/horse name that they declare to save to the Register db as its own entry through one submit button click. So I know I need a loop somewhere, likely in my controller, to loop through and grab all the entries and save them individually. However, everything I’ve tried is only saving the last event entry, ignoring all the ones before it. I’ve searched and found solutions for nested attributes or i.times options, but can’t seem to find one that would work for this.

Here’s my Register model, controller, and form view. If you want to see additional, let me know.

models/register.rb

class Register < ApplicationRecord
  belongs_to :division
  belongs_to :user
end

controllers/registers_controller.rb (new and create methods only… if more needed let me know)

  def new
    @register = Register.new
    @events = Event.where("show_id = ?", params[:show_id])
  end
...
  def create
    @events = Event.where("show_id = ?", params[:show_id])
    @register = Register.create(register_params)

    respond_to do |format|
      if @register.save
        format.html { redirect_to @register, notice: 'Register was successfully created.' }
        format.json { render :show, status: :created, location: @register }
      else
        format.html { render :new }
        format.json { render json: @register.errors, status: :unprocessable_entity }
      end
    end
  end

views/registers/_form.html.erb

<%= form_with(model: register) do |form| %>
  <% if register.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(register.errors.count, "error") %> prohibited this register from being saved:</h2>

      <ul>
        <% register.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>



   <div class="field">

     <% @events.each do |event| %>
       <tr>
         <td>
           <h1><%= event.event_name %></h1>
           <p>Event Type: <%= event.event_type %><br />
             Event Date/Time: <%= event.event_date %>, <%= event.event_time %></p>
            <p><%= event.cost %></p>
           <p><%= event.description %></p>
         </td>
         <td><%= collection_select(:register, :division_id, Division.where("show_id = ?", params[:show_id]), :id, :division_name, prompt: true, name: "register[]division_id") %></td>
         <td><%= form.text_field :horse_name %></td>
         <%= form.number_field :user_id, id: :register_user_id, value: current_user.id, type: :hidden %>
         <%= form.hidden_field :show_id, :value => params[:show_id] %>
         <%= form.hidden_field :event_id, :value => event.id %>
       </tr>
    <% end %>

   </div>

   <div class="actions">
     <%= form.submit %>
   </div>
 <% end %>

Any help is appreciated.

I think accepts_nested_attributes_for On your Registration model which should has_many :events and also fields_for @registration.events In your view

You’ll also need to modify your registration_params in your RegistrationController to include event_attributes: [your event fields you want to set]

So, you’re trying to create multiple registrations with one submit click button right?

The problem is that your parameters sent from the form only include one set of values. Only 1 show_id, 1 event_id, etc. So, the first several elements entered into the form are lost on the submission of the form. No matter what you do in the controller you can’t find those.

So, what you need to achieve is to create unique identifiers for each of the field values.

If the number of events is fixed, you can create a unique field for each. Example: show_id_1, show_id_2, show_id_3, etc. You also need to permit all of these values in the controller, and then you can process these by saving each set of values into a new record.

If the number of events is not fixed, you will need to do what Chris described. You need to create nested attributes, so the values are sent nested to the controller.

You may want to create a higher level model which has multiple nested registrations within it. For example you could call it SuperRegistration, which will have many registrations. You will serve a super_registration form to your users, and you will process those values with the super_registration controller.

If you’re stuck ask…