# How to add multiple new records from one form

**URL:** <https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394>\
**Category:** Rails\
**Created:** [February 3, 2006, 8:17pm UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394 "2006-02-03T20:17:50Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 3, 2006, 8:17pm UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/1 "2006-02-03T20:17:50Z")

</div>

I’m trying to provide our customers with a page where they can add up to  
20 items to their cart in one form. The form simply has 20 rows with  
each row containing a text input for product code and a text input for  
quantity.

I’ve tried having the controller create an array that has an object for  
each row by looping through something like:

@new\_items[1] = Cart.new

and the controller is happy with that, but the template isn’t–it gives  
an error like “@new\_items[1] is not allowed as an instance variable  
name”.

I can get the whole thing working if I use non-model form objects in the  
template, but then I lose the Rails error magic where it highlights any  
errant fields and gives a message.

Why can I create Cart objects within an array in the controller, but not  
use them in the template.

Or am I going about this completely wrong??

Any help is appreciated greatly.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 4, 2006, 7:56am UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/2 "2006-02-04T07:56:51Z")

</div>

Shawn Goble wrote:

> and the controller is happy with that, but the template isn’t–it gives  
> an error like “@new\_items[1] is not allowed as an instance variable  
> name”.

Perhaps:

\<% for i in 1…20 do %\>  
\<%= text\_field :new\_items, :product\_code, :index =\> i %\>  
\<%= text\_field :new\_items, :quantity, :index =\> i %\>  
\<% end %\>

case request.method  
when :get then @new\_items = Array.new(20) { Cart.new }  
when :post  
all\_valid = true  
@new\_items = []  
params[:new\_items].each\_value { |p| @new\_items \<\< (c=Cart.new§);  
all\_valid &&= c.valid? }  
if !@new\_items.empty? && all\_valid  
@user.items \<\< @new\_items  
@user.save(false)  
redirect\_to :action =\> ‘show\_cart’  
else  
flash[:error] = ‘No items entered’ if @new\_items.empty?  
(20-@new\_items.length).times { @new\_items \<\< Cart.new }  
end  
end

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 4, 2006, 11:28am UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/3 "2006-02-04T11:28:45Z")

</div>

Mark Reginald J. wrote:

> Shawn Goble wrote:
> 
> > and the controller is happy with that, but the template isn’t–it gives  
> > an error like “@new\_items[1] is not allowed as an instance variable  
> > name”.
> 
> Perhaps:
> 
> \<% for i in 1…20 do %\>  
> \<%= text\_field :new\_items, :product\_code, :index =\> i %\>  
> \<%= text\_field :new\_items, :quantity, :index =\> i %\>  
> \<% end %\>

Hi Mark,

My query with this is, would Rails look at the number enclosed within  
the square brackets and subsequently clobber records with id ranging  
from [1] to [20]?

The confusion stemmed about from the fact that if you provide blank  
brackets when rendering an edit form, such as:

\<% for @comment in @post.comments %\>  
\<%= text\_field ‘comment[]’, ‘author’ %\>  
\<%= text\_field ‘comment[]’, ‘body’ %\>  
\<% end %\>

It will also generate similar looking HTML tags, and hence in that case  
the number enclosed within the square brackets do have some  
significance.

Thanks.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 4, 2006, 11:52am UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/4 "2006-02-04T11:52:59Z")

</div>

Woei S. wrote:

> > \<% for i in 1…20 do %\>  
> > \<%= text\_field :new\_items, :product\_code, :index =\> i %\>  
> > \<%= text\_field :new\_items, :quantity, :index =\> i %\>  
> > \<% end %\>

> \<% end %\>
> 
> It will also generate similar looking HTML tags, and hence in that case  
> the number enclosed within the square brackets do have some  
> significance.

While the parameter hash would be similar, with id rather than index  
keys,  
you would handle it differently in the controller. The Agile book  
suggests

```
 Cart.update(params[:new_items].keys, params[:new_items].values)

```

In the code I’ve given, the keys aren’t even looked at. New records  
with new ids are created based on the hash values.

Looking over the code I see a few errors: The save of @user is not  
needed,  
and flash.now should be used, not just flash. Also, for greater  
efficiency,  
each new item should be instantiated via @user.items.build§, then, if  
all  
pass validation, saved using save(false), avoiding a second validation.

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 4, 2006, 4:50pm UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/5 "2006-02-04T16:50:11Z")

</div>

Mark Reginald J. wrote:

> Perhaps:
> 
> \<% for i in 1…20 do %\>  
> \<%= text\_field :new\_items, :product\_code, :index =\> i %\>  
> \<%= text\_field :new\_items, :quantity, :index =\> i %\>  
> \<% end %\>
> 
> case request.method  
> when :get then @new\_items = Array.new(20) { Cart.new }  
> when :post  
> all\_valid = true  
> @new\_items = []  
> params[:new\_items].each\_value { |p| @new\_items \<\< (c=Cart.new§);  
> all\_valid &&= c.valid? }  
> if !@new\_items.empty? && all\_valid  
> @user.items \<\< @new\_items  
> @user.save(false)  
> redirect\_to :action =\> ‘show\_cart’  
> else  
> flash[:error] = ‘No items entered’ if @new\_items.empty?  
> (20-@new\_items.length).times { @new\_items \<\< Cart.new }  
> end  
> end

Is this method going to flow any validation errors back to the form  
though? If it was just one new item on the form you could use:

\<%= error\_messages\_for ‘new\_items’ %\>

but I’m not clear on whether that would work with this method. Doesn’t  
it end up just like it would using non-model objects on the form and  
placing the data into Cart objects in the controller? Works, but the  
form doesn’t show the validation messages.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 6, 2006, 5:51pm UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/6 "2006-02-06T17:51:32Z")

</div>

Mark Reginald J. wrote:

> case request.method  
> when :get then @new\_items = Array.new(20) { Cart.new }  
> when :post

This still seems not to work.

If in the controller I use:

@new\_items = Cart.new

then the :index in the template seems to work correctly (even though  
I’ve only created one object in the controller). It will even save the  
information to the database correctly using that method. The downside  
is that I still can’t get validation error information back to the form.

If however, I do as you suggest (which does seem to make more sense) and  
use:

@new\_items = Array.new(20) { Cart.new }

I get the error “undefined method `product_id' for #<Array:0x55dae60>", which seems to suggest that :index isn't actually letting me reference an array but creating one after the fact from a single object. (Incidentally, if I use @new_items = Cart.new and then after :post I eventually use something like @new_items = Cart.create(items), I get the same error "undefined method`product\_id’ for #Array:0x55dae60” in the  
template.)

Thanks for the help so far, I’ve at least learned something about the  
:index parameter.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 9, 2006, 12:29pm UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/7 "2006-02-09T12:29:44Z")

</div>

Shawn Goble wrote:

> use:
> 
> @new\_items = Array.new(20) { Cart.new }
> 
> I get the error “undefined method `product\_id’ for #Array:0x55dae60”,  
> which seems to suggest that :index isn’t actually letting me reference  
> an array but creating one after the fact from a single object.

Yes, sorry, the :index parameter does not do what I thought it did.  
It replicates form fields and parameters from a single model instance,  
which is not useful for the multiple instances with validation errors  
situation you are looking for.

You may be able to make it work using some trick like:

\<% @new\_items.each\_with\_index do |@cart, i| %\>  
\<%= text\_field :cart, :product\_id, :name =\> “cart[#{i}][product\_id]” %\>  
\<% end %\>

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![Shawn\_Goble](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b5e925/32.png) [@Shawn\_Goble](https://www.ruby-forum.com/u/Shawn_Goble)\
**Post date:** [February 4, 2006, 6:17pm UTC](https://www.ruby-forum.com/t/how-to-add-multiple-new-records-from-one-form/53394/8 "2006-02-04T18:17:57Z")

</div>

Shawn Goble wrote:

> placing the data into Cart objects in the controller? Works, but the  
> form doesn’t show the validation messages.

All fields with errors will be highlighted, but to get the text  
messages you’ll need something like:

\<% for i in 1…20  
@item = @new\_items[i-1] %\>  
Item \<%= i %\>: \<%= error\_messages\_for :item %\>  
\<% end %\>

–  
We develop, watch us RoR, in numbers too big to ignore.
