From c801f233df9d20c59d9756a5279365603dc5cbbd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 16 Nov 2010 13:43:44 -0800 Subject: [PATCH] reloading an association will properly set attributes of instantiated objects. Thanks Brian Palmer [#5802 state:resolved] --- .../associations/association_collection.rb | 4 +++- .../has_many_associations_test.rb | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 7cdd91e9b2b4a..600f59026e926 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -379,7 +379,9 @@ def load_target if i @target.delete_at(i).tap do |t| keys = ["id"] + t.changes.keys + (f.attribute_names - t.attribute_names) - t.attributes = f.attributes.except(*keys) + f.attributes.except(*keys).each do |k,v| + t.send("#{k}=", v) + end end else f diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index ecfc769f3a2ab..33c53e695beb6 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1282,4 +1282,25 @@ def test_include_method_in_has_many_association_should_return_true_for_instance_ comment = post.comments.build assert post.comments.include?(comment) end + + def test_load_target_respects_protected_attributes + topic = Topic.create! + reply = topic.replies.create(:title => "reply 1") + reply.approved = false + reply.save! + + # Save with a different object instance, so the instance that's still held + # in topic.relies doesn't know about the changed attribute. + reply2 = Reply.find(reply.id) + reply2.approved = true + reply2.save! + + # Force loading the collection from the db. This will merge the existing + # object (reply) with what gets loaded from the db (which includes the + # changed approved attribute). approved is a protected attribute, so if mass + # assignment is used, it won't get updated and will still be false. + first = topic.replies.to_a.first + assert_equal reply.id, first.id + assert_equal true, first.approved? + end end