title: Using Rails models with accepts_nested_attributes_for
body: <p>I'm writing a simple Rails model called Person that <code>has_many :phone_numbers</code> and I'm trying to save the phone numbers in a complex form without manually writing setter methods. <code>accepts_nested_attributes_for</code> should do what I want but I'm having trouble getting it to work. Here's the code I have so far:</p>
  
  <p><strong>Migration</strong></p>
  
  <pre><code>class CreatePeople &lt; ActiveRecord::Migration
    def self.up
      create_table :people do |t|
        t.string :first_name
        t.string :last_name
        t.integer :address_id      
        t.string :email
  
        t.timestamps
      end
    end
  
    def self.down
      drop_table :people
    end
  end
  
  class CreatePhoneNumbers &lt; ActiveRecord::Migration
    def self.up
      create_table :phone_numbers do |t|
        t.string :number, :limit =&gt; 10
        t.string :extension, :limit =&gt; 5
        t.string :description, :null =&gt; false
        t.integer :telephone_id
        t.string :telephone_type
  
        t.timestamps
      end
    end
  
    def self.down
      drop_table :phone_numbers
    end
  end
  </code></pre>
  
  <p><strong>Models</strong></p>
  
  <pre><code>class Person &lt; ActiveRecord::Base
    has_one :address, :as =&gt; :addressable, :dependent =&gt; :destroy
    has_many :phone_numbers,
      :as =&gt; :telephone,
      :dependent =&gt; :destroy
  
    accepts_nested_attributes_for :phone_numbers
  
    attr_protected :id
  
    validates_presence_of :first_name, :last_name, :email
  end
  
  class PhoneNumber &lt; ActiveRecord::Base
    attr_protected :id
  
    belongs_to :telephone, :polymorphic =&gt; true
  end
  </code></pre>
  
  <p><strong>View</strong></p>
  
  <pre><code>&lt;% form_for @person, :builder =&gt; CustomFormBuilder do |f| %&gt;
    &lt;%= f.error_messages %&gt;
  
    &lt;%= f.text_field :first_name %&gt;
    &lt;%= f.text_field :last_name %&gt;
  
    &lt;% fields_for "person[address]", @person.address, :builder =&gt; CustomFormBuilder do |ff| %&gt;  
      &lt;%= ff.text_field :address_1 %&gt;
      &lt;%= ff.text_field :address_2 %&gt;
      &lt;%= ff.text_field :city %&gt;
      &lt;%= ff.text_field :state %&gt;
      &lt;%= ff.text_field :zip %&gt;  
    &lt;% end %&gt;
  
    &lt;h2&gt;Phone Numbers&lt;/h2&gt;
    &lt;% @person.phone_numbers.each do |phone_number| %&gt;
      &lt;% fields_for "person[phone_numbers][]", phone_number, :builder =&gt; CustomFormBuilder do |ff| %&gt;
        &lt;%= ff.text_field :description %&gt;
        &lt;%= ff.text_field :number %&gt;
        &lt;%= ff.text_field :extension %&gt;
      &lt;% end %&gt;
    &lt;% end %&gt;
  
    &lt;%= f.text_field :email %&gt;
  
    &lt;%= f.submit 'Create' %&gt;
  
  &lt;% end %&gt;
  </code></pre>
  
  <p><strong>Controller</strong></p>
  
  <pre><code>def new
    @person = Person.new 
    @person.build_address
    @person.phone_numbers.build
  
    respond_to { |format| format.html }
  end
  
  def create
    @person = Person.new(params[:person])
  
    respond_to do |format|
      if @person.save
        flash[:notice] = "#{@person.name} was successfully created."
        format.html { redirect_to(@person) }
      else
        format.html { render :action =&gt; 'new' }
      end
    end
  end
  </code></pre>
  
  <p>I have verified that a phone_numbers= method is being created, but the post still causes:</p>
  
  <pre><code>PhoneNumber(#69088460) expected, got HashWithIndifferentAccess(#32603050)
  
  RAILS_ROOT: H:/projects/test_project
  
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_proxy.rb:263:in `raise_on_type_mismatch'
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_collection.rb:319:in `replace'
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_collection.rb:319:in `each'
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_collection.rb:319:in `replace'
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations.rb:1290:in `phone_numbers='
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `send'
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `attributes='
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `each'
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `attributes='
  C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2434:in `initialize'
  H:/projects/salesguide/app/controllers/accounts_controller.rb:46:in `new'
  H:/projects/test_project/app/controllers/accounts_controller.rb:46:in `create'
  </code></pre>
  
  <p>I can get this to work by manually writing the phone_numbers= method, but this would cause a tremendous duplication of effort, I would much rather learn how to do this right. Can anybody see what I'm doing wrong?</p>