Nested attributes - not working in forms


I also posted this on
railsforum then I
realized this is probably not the best place to get answers for
this problem. So, sorry for this crosspost…

I also want to apologize for this long message. I just wanted to provide
all information - on the one hand to make the error reproducable, on the
other hand to enable people who maybe have the same problem in the
to get step-by-step instructions.

I try to generate a form with an 1:many-model. Doing so, I found the
command accepts_nested_attributes_for. However, in my form only the
parent-model gets saved, while the child-model stays empty.

I started by creating a project (I called it PhoneBook) in Rails 4.
Then I generated two models and started the migration:

$ rails g model person name
invoke active_record
create db/migrate/20130710205309_create_people.rb
create app/models/person.rb
invoke test_unit
create test/models/person_test.rb
create test/fixtures/people.yml
$ rails g model phone person_id:integer phone_number:integer
invoke active_record
create db/migrate/20130710205415_create_phones.rb
create app/models/phone.rb
invoke test_unit
create test/models/phone_test.rb
create test/fixtures/phones.yml
$ rake db:migrate
== CreatePeople: migrating

– create_table(:people)
→ 0.0008s
== CreatePeople: migrated (0.0008s)

== CreatePhones: migrating

– create_table(:phones)
→ 0.0007s
== CreatePhones: migrated (0.0008s)

Next, I specified the models


class Person < ActiveRecord::Base

has_many :phones

accepts_nested_attributes_for :phones



class Phone < ActiveRecord::Base

belongs_to :person


Then I created a controller for person

$ rails g controller people
create app/controllers/people_controller.rb
invoke erb
create app/views/people
invoke test_unit
create test/controllers/people_controller_test.rb
invoke helper
create app/helpers/people_helper.rb
invoke test_unit
create test/helpers/people_helper_test.rb
invoke assets
invoke coffee
create app/assets/javascripts/
invoke scss
create app/assets/stylesheets/people.css.scss

This controller was filled with the following code

class PeopleController < ApplicationController
def new
@person =

def create
@person =

redirect_to people_path


def index
@person = Person.all


def person_params
params.require(:person).permit(:name, phone_attributes: [ :id,
:phone_number ])


Of course I also needed some views. This one just shows the list of all
people with their phone numbers

Phone Book

    <% @person.each do |person| %>

  • <%= %>

        <% person.phones.each do |phone| %>
            <%= phone.phone_number %>
        <% end %>

    <% end %>

and this one is the interesting part: here’s my code for the form that
should create new people and phone numbers:

<%= form_for :person, url: people_path do |f| %>

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.fields_for :phones do |f_phone| %>

<%= f_phone.label :phone_number %>

<%= f_phone.text_field :phone_number %>

<% end %>

<%= f.submit %>

<% end %>

To make it work (well it doesn’t work, but almost) I also need a route

PhoneBook::Application.routes.draw do
resources :people

Are you still with me? Great! Creating a new person with a phone number
the rails console works without any problems. However, when I try my
only the Person gets stored, while the phone number is lost.

Can you help me with this problem? What am I doing wrong?

Do I maybe need a controller for phone_number? As it is only accessed
person, I thought I wouldn’t need one.

Thank you in advance!

The fields_for form helper can only loop over association phone numbers
that exist. The way to have new phone numbers added is to build them in
advance. E.g.

Or if you want to supply 4 phone number fields:

4.times {}

In that case you should add a reject_if option to your
accept_nested_attributes :phone statement to have empty left phone

You can build the phone numbers in you controller or use a form_helper
setup_person(person) in your forms.

See this Rails Cast:

Thank you, especially for linking the Railcast!

Watching this railcast helped me solving tis problem. However, .build is
just an alias for .new, which I have already in def new.

The problem was about this line in the view:

<%= form_for :person, url: people_path do |f| %>

It should be

<%= form_for @person, url: people_path do |f| %>
Am Samstag, 13. Juli 2013 13:35:34 UTC+2 schrieb javinto:


Something else: a dedicated form object would be a better practise,
Is there a detailled instruction on how to make a form object? Or a
tutorial on adding classes not connected to ActiveRecords in general?

Thank you!