diff options
author | Andrew Kaspick <andrew@redlinesoftware.com> | 2011-12-14 20:13:03 -0600 |
---|---|---|
committer | Andrew Kaspick <andrew@redlinesoftware.com> | 2011-12-14 20:13:03 -0600 |
commit | 774ff18c095145f544e845dbb940378546748969 (patch) | |
tree | 2790c29a416f4492690222fd36b6f4f500b8a942 | |
parent | b6105b0b59073efe7d8c5fad0b2246d0534030e1 (diff) | |
download | rails-774ff18c095145f544e845dbb940378546748969.tar.gz rails-774ff18c095145f544e845dbb940378546748969.tar.bz2 rails-774ff18c095145f544e845dbb940378546748969.zip |
Allow nested attributes in associations to update values in it's owner object. Fixes a regression from 3.0.x
-rw-r--r-- | activerecord/lib/active_record/associations/association.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/base.rb | 12 | ||||
-rw-r--r-- | activerecord/test/cases/nested_attributes_test.rb | 5 | ||||
-rw-r--r-- | activerecord/test/models/bird.rb | 5 |
4 files changed, 22 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index d1e3ff8e38..861dda618a 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -230,6 +230,8 @@ module ActiveRecord end def build_record(attributes, options) + attributes = (attributes || {}).reverse_merge(creation_attributes) + reflection.build_association(attributes, options) do |record| record.assign_attributes( create_scope.except(*record.changed), diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 9215a68cfc..2d2909054d 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1776,6 +1776,7 @@ MSG attributes = new_attributes.stringify_keys multi_parameter_attributes = [] + nested_parameter_attributes = [] @mass_assignment_options = options unless options[:without_protection] @@ -1786,12 +1787,21 @@ MSG if k.include?("(") multi_parameter_attributes << [ k, v ] elsif respond_to?("#{k}=") - send("#{k}=", v) + if v.is_a?(Hash) + nested_parameter_attributes << [ k, v ] + else + send("#{k}=", v) + end else raise(UnknownAttributeError, "unknown attribute: #{k}") end end + # assign any deferred nested attributes after the base attributes have been set + nested_parameter_attributes.each do |k,v| + send("#{k}=", v) + end + @mass_assignment_options = nil assign_multiparameter_attributes(multi_parameter_attributes) end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 2ae9cb4888..2f28dd4767 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -617,6 +617,11 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name] end + def test_should_take_a_hash_with_owner_attributes_and_assign_the_attributes_to_the_associated_model + @pirate.birds.create :name => 'bird', :pirate_attributes => {:id => @pirate.id.to_s, :catchphrase => 'Holla!'} + assert_equal 'Holla!', @pirate.reload.catchphrase + end + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}" do @pirate.attributes = { association_getter => [{ :id => 1234567890 }] } diff --git a/activerecord/test/models/bird.rb b/activerecord/test/models/bird.rb index e61d48e6a5..dff099c1fb 100644 --- a/activerecord/test/models/bird.rb +++ b/activerecord/test/models/bird.rb @@ -1,9 +1,12 @@ class Bird < ActiveRecord::Base + belongs_to :pirate validates_presence_of :name + accepts_nested_attributes_for :pirate + attr_accessor :cancel_save_from_callback before_save :cancel_save_callback_method, :if => :cancel_save_from_callback def cancel_save_callback_method false end -end
\ No newline at end of file +end |