Nested attributes - not working in forms

I also posted this on railsforum but 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 future 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 of course:

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

Are you still with me? Great! Creating a new person with a phone number in the rails console works without any problems. However, when I try my form, 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 via 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 numbers skipped.

You can build the phone numbers in you controller or use a form_helper like 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| %>


Something else: a dedicated form object would be a better practise, right? 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!