Topic: Nested attributes - not working in forms
First of all I want to apologize for this long post. 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
# app/models/person.rb class Person < ActiveRecord::Base has_many :phones accepts_nested_attributes_for :phones end
# app/models/phone.rb class Phone < ActiveRecord::Base belongs_to :person end
Then I created a controller for person
This controller was filled with the following code
class PeopleController < ApplicationController def new @person = Person.new @person.phones.new end def create @person = Person.new(person_params) @person.save redirect_to people_path end def index @person = Person.all end private def person_params params.require(:person).permit(:name, phone_attributes: [ :id, :phone_number ]) end end
Of course I also needed some views. This one just shows the list of all people with their phone numbers
<h1>Phone Book</h1> <ul> <% @person.each do |person| %> <li> <h2> <%= person.name %> </h2> <ul> <% person.phones.each do |phone| %> <li> <%= phone.phone_number %> </li> <% end %> </ul> </li> <% end %> </ul>
and this one is the [p]interesting part[/p]: here's my code for the form that should create new people and phone numbers:
<%= form_for :person, url: people_path do |f| %> <p> <%= f.label :name %><br /> <%= f.text_field :name %> </p> <%= f.fields_for :phones do |f_phone| %> <div class="field"> <p> <%= f_phone.label :phone_number %><br /> <%= f_phone.text_field :phone_number %> </p> </div> <% end %> <p> <%= f.submit %> </p> <% 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 end
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!
Last edited by Spindoctor (2013-07-10 19:42:15)