# How do you create a controller & view to create a list of ob

**URL:** <https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396>\
**Category:** Rails\
**Created:** [May 31, 2006, 4:22am UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396 "2006-05-31T04:22:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [May 31, 2006, 4:22am UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/1 "2006-05-31T04:22:34Z")

</div>

I’m trying to figure out how to design a view and controller to work  
with a  
simple collection. I have a Foo that has many Bars, so here’s what I  
did:

$ ruby script/generate model Foo  
$ ruby script/generate model Bar  
(Uncomment t.column, :name: :string in foo and bar migrations)  
(Edit Foo.rb and Bar.rb, add has\_many :bars to Foo, belongs\_to :foo to  
Bar)  
$ rake db:migrate  
$ ruby script/generate scaffold Foo

At this point you can create/edit foos, but no bars. So what I want to  
be  
able to do it create 5 bars at the same time I create a foo. So the  
form  
would look like this:

Name: [_**]  
Bar #1 Name: [**_]  
Bar #2 Name: [_**]  
Bar #3 Name: [**_]  
Bar #4 Name: [_**]  
Bar #5 Name: [**_]

So, trying to follow the example from  
[ActionView::Helpers::FormHelper](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html), I  
added this to app/views/foos/\_form.rhtml:

\<% 5.times do |i| %\>

\<%= text\_field 'bar[]', 'name' %\>

\<% end %\>

But I get this error:

You have a nil object when you didn’t expect it!  
You might have expected an instance of ActiveRecord::Base.  
The error occured while evaluating nil.id\_before\_type\_cast

Extracted source (around line #9):

6:  
7: \<% 5.times do |i| %\>  
8:

9: \<%= text\_field ‘bar[]’, ‘name’ %\>

  
10: \<% end %\>  
11:  
12: 

Hmmm… so I guess I need a bar array that is initialized with Bar  
objects?  
So I add this to the new method in the FooController:

```
@bars = []
5.times do |i|
  @bars.push Bar.new
end

```

But then I get this error:

undefined method `id\_before\_type\_cast’ for #Array:0x3925ee8

Extracted source (around line #9):

6:  
7: \<% 5.times do |i| %\>  
8:

9: \<%= text\_field ‘bars[]’, ‘name’ %\>

  
10: \<% end %\>  
11:  
12: 

So I’m stuck, how are you supposed to do this?

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 3:03am UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/2 "2006-06-01T03:03:30Z")

</div>

Thanks to some help from people in #rubyonrails, I’ve made some progress  
on  
this. Handling an object graph is definately a weakness of Ruby on  
Rails  
when compared to other web frameworks, such as Webwork. First of all,  
for  
any non-Java Railers, Webwork is a Java MVC framework. When working  
with an  
object graph, you use Object Graph Navigation Language (OGNL) to specify  
the  
properties in the forms. For example, lets say you want to have a form  
that  
has a User object that has a property that is a Collection of Addresses.  
You first define you model objects:

public class User {  
private List addresses = new ArrayList();  
}

public class Address {  
private String street;  
private String city;  
//etc.  
}

Yes, you need to make getters and setters, there is no attr for Java 🙂

Then, create an Action, which is Webwork terminology for a Controller.  
Then  
you define the class properties for the Action (again, can’t just do it  
on  
the fly, this is a staticly typed language we’re dealing with)

public class UsersAction {  
private User user = new User();  
}

So, there is a little more work here setting this up, because you’re  
dealing  
with Java instead of Ruby, but here’s where Java/Webwork wins out over  
Ruby  
on Rails. In your view, you might have this:

Then when you submit your form, Webwork’s type conversion takes care of  
things just like you’d want. The city property of the 3rd element (zero  
based index) of the user’s addresses is set to that value of these  
field.

As far as I can tell, you can’t do this with Ruby on Rails. The problem  
lies in the fact that RoR converts the params into a Hash of Hashes. So  
sticking with the example above, you’d like to have a form like this:

\<%= text\_field ‘user[address]’, ‘name’, “index” =\> i %\>

But that doesn’t work. The only way around it seems to be to create an  
addresses Array in the controller, then putting it back into the user on  
submit. Then, in the controller, you’d have to do this:

def new  
@user = User.new  
@addresses = []  
5.times {|i| @addresses.push Address.new}  
end

And that assumes you know exactly how many Addresses that you will have.  
Any way, then when you submit it, you need to put it back together:

def create  
@user = User.new(params[:user])  
@user.addresses = params[:user].values.collect {|a| Address.new(a)}  
end

I’ve got this simple example to work, put I’m having problems getting it  
work with a more complex example. So, somebody prove me wrong. Tell me  
there’s a better way to handle an object graph with Ruby On Rails.

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 3:53pm UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/3 "2006-06-01T15:53:38Z")

</div>

I’m still having no luck with trying to create an object with n child  
objects through a form. I feel like I’m close though, hoping someone  
can  
help me figure it out. What basically happens is that when my form is  
submitted to the controller, I have a Foo object and it has a bars  
property. Everything is getting populated, the bars property has 5 Bar  
objects, but each Bar object’s foo\_id is nil. That makes sense, because  
the  
Foo itself hasn’t been created yet, so there is no id. My hope would be  
that AR would save the Foo to the DB first, then populate the foo\_id of  
each  
Bar, then save each Bar. But instead I get 5 “Bars is Invalid” errors,  
one  
for each Bar in foo.bars. Has anybody been able to create an object  
with  
child objects using RoR? If so, what am I doing wrong? Here’s my code:

#Pretty standard model classes  
class Foo \< ActiveRecord::Base  
has\_many :bars  
end

class Bar \< ActiveRecord::Base  
belongs\_to :foo  
validates\_presence\_of :foo\_id  
end

#Controller with just the relevant methods shown here, new and create  
#I am doing something a little funky here  
#The form submits to /foos/new instead of /foos/create  
#The new method calls create if the request is a post  
#This allows me to easily show the form again if there is a problem  
#without explicitly rendering the template or calling the new method  
class FoosController \< ApplicationController

…

def new  
if request.post?  
create  
else  
@foo = Foo.new  
@bars = []  
5.times {|i| @bars.push Bar.new} #There’s probably a cleaner way  
to do  
this  
end  
end

def create  
@foo = Foo.new(params[:foo])  
@foo.bars = params[:bar].values.collect {|bar| Bar.new(bar)}  
if @foo.save  
flash[:notice] = ‘Foo was successfully created.’  
redirect\_to :action =\> ‘list’  
end  
@bars = @foo.bars  
end

…

end

#The form partial for foo \_form.rhtml:

Name  
\<%= text\_field 'foo', 'name' %\>

\<% @bars.each\_index do |i| %\>

Bar #\<%=i%\>:   
\<%= text\_field 'bar', 'name', "index" =\> i %\>

\<% end %\>

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 5:34pm UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/4 "2006-06-01T17:34:37Z")

</div>

Could you do:

foo = Foo.new  
foo.save

if foo.errors.empty?  
params[:bars].each do |bar|  
foo.bars.create(bar)  
end  
end

I think the trouble with any of these methods is error handling.  
Thinking about it, you would have to check that all the bars were valid  
first. Could get kinda complicated.

When i’ve _had_ to do this, i’ve created the parent then the children as  
above. For error checking i check the creation of each child and make a  
custom hash of errors. That’s as hacky as hell though and was more of a  
necessity than a well thought out solution :0)

Steve

Paul B. wrote:

> Alright, I’ve boiled this problem down to a specific AR thing, using  
> script/console instead of the forms and controllers:
> 
> C:\ruby\workspace\eval\>ruby script/console  
> Loading development environment.
> 
> > > foo = Foo.new  
> > > =\> #\<Foo:0x3e3c1e0 @attributes={“name”=\>nil}, @new\_record=true\>
> > 
> > > foo.bars = []  
> > > =\> []
> > 
> > > foo.bars \<\< Bar.new  
> > > =\> [#\<Bar:0x3e27330 @attributes={“name”=\>nil, “foo\_id”=\>nil},  
> > > @new\_record=true\>]
> > 
> > > foo.save!  
> > > ActiveRecord::RecordInvalid: Validation failed: Bars is invalid  
> > > from c:/ruby/ruby-  
> > > 1.8.4\_16/lib/ruby/gems/1.8/gems/activerecord-1.14.2/lib/active\_record/validations.rb:736:in`save!’  
> > > from (irb):4
> > 
> > >
> 
> So I guess AR doesn’t know how to save a new record that has child  
> records?  
> Is this the only way to do it:
> 
> C:\ruby\workspace\eval\>ruby script/console  
> Loading development environment.
> 
> > > foo = Foo.new  
> > > =\> #\<Foo:0x3e3c1e0 @attributes={“name”=\>nil}, @new\_record=true\>
> > 
> > > foo.save  
> > > =\> true
> > 
> > > foo.bars \<\< Bar.new  
> > > =\> [#\<Bar:0x3e250b0 @errors=#\<ActiveRecord::Errors:0x3e22878 @errors={},  
> > > @base=#\<Bar:0x3e250b0 …\>\>, @attributes={“name”=\>nil, “foo\_id”=\>4,  
> > > “id”=\>11}, @new\_record=false\>]
> > 
> > > foo.save  
> > > =\> true
> > 
> > >
> 
> If that’s the case, I guess I should probably create a  
> foo.save\_with\_barsmethod to encapsulate this. Is this how other  
> people are handling saving a  
> record that has\_many other records?

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 5:58pm UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/5 "2006-06-01T17:58:20Z")

</div>

So now I’m trying to create a method that copies the bars into a  
temporary  
array, saves the Foo, then adds the bars back to the Foo, and save the  
foo  
again. Seems to be the only way this is going to work. In the porcess,  
I’ve run across something about Ruby that is weird (probably only weird  
because I’m used to the Java way of things). Here’s my method:

def save\_new  
logger.debug “self.bars = #{self.bars.inspect}”  
tmp = self.bars  
self.bars = []  
logger.debug “tmp = #{tmp.inspect}”  
logger.debug “self.bars = #{self.bars.inspect}”  
end

Ignore the fact that this does nothing for now. Being a Java programmer  
here, the way I read what this code does is:

Assign the variable tmp to point to the object that self.bars points to  
Assign the variable self.bars to point to a new object, an empty array

So I would expect the variable tmp to still be pointing to the original  
array that self.bars points to. But I guess that’s not the case with  
Ruby?  
When you run it, it prints this:

self.bars = [#\<Bar:0x3ce0888 …  
tmp = []  
self.bars = []

So I assume tmp is pointing to the variable (or maybe the word reference  
is  
more appropriate?) self.bars, not what self.bars points to. And once I  
make  
self.bars point to something else, tmp then in turn points to that. So  
in  
otherwords, tmp is a reference to a reference, and self.bars is a  
reference  
to an Array. Just looking for someone to confirm what I’m finding and  
that  
I actually understand what is going on.

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 5:20pm UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/6 "2006-06-01T17:20:13Z")

</div>

Alright, I’ve boiled this problem down to a specific AR thing, using  
script/console instead of the forms and controllers:

C:\ruby\workspace\eval\>ruby script/console  
Loading development environment.

> > foo = Foo.new  
> > =\> #\<Foo:0x3e3c1e0 @attributes={“name”=\>nil}, @new\_record=true\>
> 
> > foo.bars = []  
> > =\> []
> 
> > foo.bars \<\< Bar.new  
> > =\> [#\<Bar:0x3e27330 @attributes={“name”=\>nil, “foo\_id”=\>nil},  
> > @new\_record=true\>]
> 
> > foo.save!  
> > ActiveRecord::RecordInvalid: Validation failed: Bars is invalid  
> > from c:/ruby/ruby-  
> > 1.8.4\_16/lib/ruby/gems/1.8/gems/activerecord-1.14.2/lib/active\_record/validations.rb:736:in`save!’  
> > from (irb):4
> 
> >

So I guess AR doesn’t know how to save a new record that has child  
records?  
Is this the only way to do it:

C:\ruby\workspace\eval\>ruby script/console  
Loading development environment.

> > foo = Foo.new  
> > =\> #\<Foo:0x3e3c1e0 @attributes={“name”=\>nil}, @new\_record=true\>
> 
> > foo.save  
> > =\> true
> 
> > foo.bars \<\< Bar.new  
> > =\> [#\<Bar:0x3e250b0 @errors=#\<ActiveRecord::Errors:0x3e22878 @errors={},  
> > @base=#\<Bar:0x3e250b0 …\>\>, @attributes={“name”=\>nil, “foo\_id”=\>4,  
> > “id”=\>11}, @new\_record=false\>]
> 
> > foo.save  
> > =\> true
> 
> >

If that’s the case, I guess I should probably create a  
foo.save\_with\_barsmethod to encapsulate this. Is this how other  
people are handling saving a  
record that has\_many other records?

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 11:48pm UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/7 "2006-06-01T23:48:13Z")

</div>

> So when you assign self.bars = [] you are changing the object that  
> self.bars is pointing at and therefor the tmp var is pointing at the  
> same  
> object.

Yeah, that’s the fundamental difference between Ruby and Java. In Java,  
self.bars = [] has no effect at all on the object that self.bars was  
originally pointing to. You are just making the reference self.bars  
point  
at a new object, not changing the object that self.bars points to.

Anyway, I’ll give your controller code a try. That makes sense, why  
would I  
put the bars into foo, only to take them out temporarily and then add  
them  
back in. My thinking though was more along the lines of the separation  
between the controller and the model. The controller just wants the  
whole  
object graph to be saved, so delagate it to the model. But that just  
isn’t  
the way it works, because like you said, AR doesn’t populate the foo\_id  
of  
each bar. Thanks for your help, I’ll let you know how it turns out.

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [June 1, 2006, 9:51pm UTC](https://www.ruby-forum.com/t/how-do-you-create-a-controller-view-to-create-a-list-of-ob/95396/8 "2006-06-01T21:51:38Z")

</div>

Paul-

```
You are correct. In ruby variables are kind of like pointers to

```

objects. When you assign tmp = self.bars they both now point to the  
same object. So when you assign self.bars = [] you are changing the  
object that self.bars is pointing at and therefor the tmp var is  
pointing at the same object. You can get around this by doing tmp =  
self.bars.dup and then continue on with what you are doing.

```
But I don't understand why you are trying to set self.bars to be an

```

empty array? Lets look at how you can accomplish this in your  
controller. Since you have set validates\_presence\_of :foo\_id in your  
comments model you have to either use create to make a new foo or  
foo.save before you can add comments to it. This is because there is  
no foo\_id for the bars to use until you save foo to the db and it  
gets an id

# One liner 😉

@foo = Foo.create(:name =\> ‘First Foo!’).bars \<\< params[:bars].map  
{ |bar| Bar.create(bar) }

#OR with error handling  
if @foo = Foo.new(:name =\> ‘First Foo!’).save  
@foo.bars \<\< params[:bars].map { |bar| Bar.new(bar) }  
if @foo.bars.each {|bar| bar.valid?}  
@foo.save  
else  
# bars have errors  
end  
else

# foo has errors

end

```
Depending on what you are trying to do you might want to look at

```

validates\_associated instead of valiodates\_presence\_of :foo\_id.

Cheers-  
-Ezra
