Reputation: 67
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
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
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