nathanielelliott
nathanielelliott

Reputation: 67

Creating multiple entries on one model - Ruby on Rails (non nested)

I am having a difficult time finding information on this but think the solution is a simple one. In short, I need to have the ability to add multiple entries to one model at one time. The user story goes like this: User selects "Add New" and is directed to the page where they can add simply ONE entry or select a drop down of the desired entries they want to add.

All the posts I see have information about doing this with objects that are nested but I am just using one model. Do I need to follow the same protocol? Is there a simpler way? Am I just searching for the wrong terminology since being new to Ruby?

The basic application looks like this:

ticket_controller.rb

def new
   @ticket = Ticket.new
end
def create
tnum = gets.chomp
tnum.times do Ticket.new(ticket_params)

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

new.html.erb

<h1>New ticket</h1>

<%= render 'form' %>

<%= link_to 'Back', tickets_path %>

I have looked throughout the site and just think I am missing something! Thanks for pointing me in the direction needed.

_form.html.erb

<%= form_for(@ticket) do |f| %>
<% tnum.times do |index|%>
  <div class="field">
    <%= f.label :type %><br>
    <%= f.text_field :type %>
  </div>
  <div class="field">
    <%= f.label :amount %><br>
    <%= f.text_field :amount %>
  </div>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Upvotes: 2

Views: 715

Answers (2)

rainkinz
rainkinz

Reputation: 10404

There must be a better way, but this one way to do it. (Note I normally use a 'Form Object' but for this example I'll just use the raw collection):

In your controller change the object passed to the new form to be an array (in this case I'll pre-populate it):

  def new
    @tickets = [Ticket.new(title: 'New Ticket')]
  end

Then in your new template you need to update it to iterate over the tickets array:

<%= form_tag tickets_path do |f| %>

  <% @tickets.each do |ticket| %>
    <%= fields_for "tickets[#{ticket.object_id}]", ticket do |builder| %>
      <%= render 'ticket_fields', f: builder %>
    <% end %>
  <% end %>

  <%= link_to_add_ticket "Add Tickets" %>

  <%= submit_tag %>
<% end %>

The ticket fields partial looks like:

<fieldset>
  <%= f.label :content, "Ticket" %><br />
  <%= f.text_field :title %><br />
</fieldset>

For good measure add a helper to allow you to add new tickets dynamically:

module TicketsHelper

  def link_to_add_ticket(name)
    # create a new object for the form
    new_object = Ticket.new

    # get an id for javascript to hook into
    id = new_object.object_id

    fields = fields_for("tickets[#{id}]", new_object) do |builder|
      render("ticket_fields", f: builder)
    end
    link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
  end

end

and you need some coffee script to wire that up:

jQuery ->
  $('form').on 'click', '.add_fields', (event) ->
    time = new Date().getTime()
    regexp = new RegExp($(this).data('id'), 'g')
    $(this).before($(this).data('fields').replace(regexp, time))
    event.preventDefault()

Basically all of this is an adaption of this railscast which might be helpful: http://railscasts.com/episodes/196-nested-model-form-revised however, that is dealing with the more classic nested model.

Upvotes: 2

Justus Eapen
Justus Eapen

Reputation: 1159

Couldn't you save the number of tickets the user wants to purchase to a variable, then pass that integer to a times loop? Like so:

#gets from form
ticket_buys = gets.chomp

ticket_buys.times do Ticket.new(ticket_params)

Upvotes: 0

Related Questions