2

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

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Missing template tickets/create, application/create with is the only error I now receive, working on this and will share what I find! Thanks again for your help!
It seems to be losing the array through the process. Has anyone else seen this yet?
0

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)

3 Comments

I had tried something like that but couldn't figure out the form side to iterate through the chomp that I received. I kept getting an error unexpected $end when I would iterate through.
Hmm. Could you assign quantity as an attribute of the ticket model?
I just updated it with the idea I had started with but couldn't get past the error.

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.