# Doubly-nested models

**URL:** <https://www.ruby-forum.com/t/doubly-nested-models/175835>\
**Category:** Rails\
**Created:** [September 21, 2009, 6:05am UTC](https://www.ruby-forum.com/t/doubly-nested-models/175835 "2009-09-21T06:05:11Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [September 21, 2009, 6:05am UTC](https://www.ruby-forum.com/t/doubly-nested-models/175835/1 "2009-09-21T06:05:11Z")

</div>

Hi all,

I have three models, like so:

User  
belongs\_to :person  
accepts\_nested\_attributes\_for :person, :allow\_destroy =\> false  
has\_many :contacts

Person  
has\_many :contacts  
accepts\_nested\_attributes\_for :contacts, :allow\_destroy =\> true

Contact  
belongs\_to :person

And actually, it’s a bit more complicated because Contact uses single-  
table polymorphism and may be a PhoneNumber or an Address. Different  
information would be filled in for each on the form, so right now I  
have separate partials for each of those.

My goal is to create both the User and the Person, as well as a  
Contact (if specified), when the first form is submitted. I’ve got it  
so it creates the User and the Person, but it doesn’t set any of the  
data in the Person row. It won’t create any Contacts at all.

# new.html.erb

# Sign up

\<% form\_for @user, :url =\> account\_path do |f| %\>  
\<%= f.error\_messages %\>  
\<%= render :partial =\> “form”, :object =\> f %\>

\<%= f.submit "Register" %\>

\<% end %\>
# \_form.html.erb

\<%= error\_messages\_for :user %\>

 \<% form\_for @user do |user\_form| -%\>

```
<%= user_form.label :email %><br />
<%= user_form.text_field :email %><br />
<br />
<%= user_form.label :password, user_form.object.new_record? ?

```

nil : “Change password” %\>  
  
\<%= user\_form.password\_field :password %\>  
  
  
  
\<%= user\_form.label :password\_confirmation, ‘Confirm’ %\>  
  
\<%= user\_form.password\_field :password\_confirmation %\>  
  
  
  
\<%= render :partial =\> “person”, :object =\> @person %\>  
\<% end -%\>

  

# \_person.html.erb

 \<% form\_for @person do |person\_form| -%\>

```
<%= person_form.label :title %><br />
<%= person_form.text_field :title %><br />
<br />
<%= person_form.label :first_name %><br />
<%= person_form.text_field :first_name %><br />
<br />
<%= person_form.label :last_name %><br />
<%= person_form.text_field :last_name %><br />
<br />
<%= person_form.label :job_title %><br />
<%= person_form.text_field :job_title %><br />
<br />
<div id="contacts">
  <%= render :partial => "address", :collection =>

```

@person.addresses %\>  
\<%= render :partial =\> “phone\_number”, :collection =\>  
@person.phone\_numbers %\>

  

\<%= add\_contact\_link :address %\>  
\<%= add\_contact\_link :phone\_number %\>

  
\<% end -%\>
# \_phone\_number.html.erb (\_address is very similar)

 \<% new\_or\_existing = phone\_number.new\_record? ? 'new' : 'existing' %\> \<% prefix = "person[#{new\_or\_existing}\_contact\_attributes][]" %\>

\<% fields\_for prefix, phone\_number do |contact\_form| -%\>

\<%= contact\_form.hidden\_field :type %\>  
Area + Phone \<%= contact\_form.text\_field :value %\>  
  
\<%= remove\_contact\_link :phone\_number, ‘remove’ %\>

  
\<% end -%\>

# users\_controller.rb

def new  
@user = User.new  
@person = @user.build\_person  
@addresses = @person.addresses.build  
@phone\_numbers = @person.phone\_numbers.build  
end

# POST /users

# POST /users.xml

def create  
@user = User.new(params[:user])  
if @user.save  
flash[:notice] = ‘User was successfully registered.’  
redirect\_back\_or\_default account\_url  
else  
render :action =\> :new  
end  
end

Any thoughts? Apologies if things are a little unorthodox. I’ve been  
fiddling for hours.

Thanks,  
John

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [September 21, 2009, 3:20pm UTC](https://www.ruby-forum.com/t/doubly-nested-models/175835/2 "2009-09-21T15:20:08Z")

</div>

If I recall correctly, you can’t nest forms, which is what your \_person  
partial is attempting to do.

I don’t have the references handy, but google for rails multipart forms  
and you should get some hits.

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [September 21, 2009, 3:32pm UTC](https://www.ruby-forum.com/t/doubly-nested-models/175835/3 "2009-09-21T15:32:12Z")

</div>

Ar Chron wrote:

> If I recall correctly, you can’t nest forms, which is what your \_person  
> partial is attempting to do.

That is correct. HTML doesn’t allow nesting of elements. Since  
each form\_for creates a tag, you’re producing bad HTML. Replace  
the inner form\_for with fields\_for.

> I don’t have the references handy, but google for rails multipart forms  
> and you should get some hits.

Stephen Chu’s params[:fu] series is lovely, though perhaps slightly out  
of date. Have a look at it.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![princenamor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/c0e974/32.png) [@princenamor](https://www.ruby-forum.com/u/princenamor)\
**Post date:** [September 21, 2009, 7:51pm UTC](https://www.ruby-forum.com/t/doubly-nested-models/175835/4 "2009-09-21T19:51:11Z")

</div>

Thanks all, think I fixed it, mostly.

UsersController:  
def create  
@user = User.new(params[:user])  
@person = @user.build\_person(params[:user][:person])  
@person.contacts\_attributes = params[:person][:contacts]  
if @user.save  
flash[:notice] = ‘User was successfully registered.’  
redirect\_back\_or\_default account\_url  
else  
render :action =\> :new  
end  
end

def new  
@user = User.new  
@person = @user.build\_person  
@person.addresses.build  
@person.phone\_numbers.build  
end

new.html.erb:

# Sign up

\<% form\_for @user, :url =\> account\_path do |f| %\>  
\<%= f.error\_messages %\>  
\<%= render :partial =\> “form”, :object =\> f %\>

\<%= f.submit "Register" %\>

\<% end %\>

\_form.html.erb  
\<%= error\_messages\_for :user %\>

 \<% form\_for @user do |user\_form| -%\>

```
<%= user_form.label :email %>
<%= user_form.text_field :email %>
<br />
<%= user_form.label :password, user_form.object.new_record? ?

```

nil : “Change password” %\>  
\<%= user\_form.password\_field :password %\>  
  
  
\<%= user\_form.label :password\_confirmation, ‘Confirm’ %\>  
\<%= user\_form.password\_field :password\_confirmation %\>  
  
  
\<%= render :partial =\> “person”, :object =\> @person %\>  
\<% end -%\>

  

\_person.html.erb:

 \<% fields\_for @person do |person\_form| -%\>

```
<%= person_form.label :title %><%= person_form.select :title,

```

Person::TITLES %\>  
\<%= person\_form.label :first\_name %\>\<%=  
person\_form.text\_field :first\_name %\>  
\<%= person\_form.label :last\_name %\>\<%=  
person\_form.text\_field :last\_name %\>  
  
  
  
\<%= person\_form.label :job\_title %\>  
  
\<%= person\_form.text\_field :job\_title %\>

  
\<%= render :partial =\> “address”, :collection =\>  
@person.addresses %\>  
\<%= render :partial =\> “phone\_number”, :collection =\>  
@person.phone\_numbers %\>  

  

\<%= add\_contact\_link :address %\>  
\<%= add\_contact\_link :phone\_number %\>

  
\<% end -%\>

\_address.html.erb:

 \<% fields\_for "person[contacts][]", address do |contact\_form| -%\> 

Address  
 \<%= contact\_form.hidden\_field :type %\>  
 \<%= contact\_form.select :label, Address::LABELS, :selected =\> Address::LABELS.first %\> Street \<%= contact\_form.text\_field :value %\>  
 Zip+4 \<%= contact\_form.text\_field :zip\_plus\_four, :limit =\> 10 %\> \<%= remove\_contact\_link :address, 'remove' %\>

 \<% end -%\>

And phone number is about the same as that.

The only problem is that it won’t save the contents of the :type  
hidden\_field in the last partial. It fails to validate. That’s a topic  
for another post, though, I suppose.
