Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing Rails models with accepts_nested_attributes_for
    text
    copied!<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>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload