aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-05-11 19:40:26 +0900
committerRyuta Kamizono <kamipo@gmail.com>2018-05-11 19:57:22 +0900
commitab3ad6a9ad119825636153cd521e25c280483340 (patch)
treeef7e87a1e06d771f24d7eb714a9623dc36b6431a /activerecord
parent5ed8aa9e02014d7840e746f407068315d6fc6b63 (diff)
downloadrails-ab3ad6a9ad119825636153cd521e25c280483340.tar.gz
rails-ab3ad6a9ad119825636153cd521e25c280483340.tar.bz2
rails-ab3ad6a9ad119825636153cd521e25c280483340.zip
`becomes` should clear the mutation tracker which is created in `after_initialize`
`becomes` creates new object and copies attributes from the receiver. If new object has mutation tracker which is created in `after_initialize`, it should be cleared since it is for discarded attributes. But if the receiver doesn't have mutation tracker yet, it will not be cleared properly. It should be cleared regardless of whether the receiver has mutation tracker or not. Fixes #32867.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb2
-rw-r--r--activerecord/lib/active_record/persistence.rb2
-rw-r--r--activerecord/test/cases/persistence_test.rb11
-rw-r--r--activerecord/test/models/topic.rb2
4 files changed, 14 insertions, 3 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 7ff467b033..233ee29fac 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -157,7 +157,7 @@ module ActiveRecord
# original attribute values in the database (as opposed to the in-memory
# values about to be saved).
def attributes_in_database
- changes_to_save.transform_values(&:first)
+ mutations_from_database.changed_values
end
private
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index c2393c1fc8..a0d5f1ee9f 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -373,7 +373,7 @@ module ActiveRecord
became = klass.allocate
became.send(:initialize)
became.instance_variable_set("@attributes", @attributes)
- became.instance_variable_set("@mutations_from_database", @mutations_from_database) if defined?(@mutations_from_database)
+ became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
became.instance_variable_set("@new_record", new_record?)
became.instance_variable_set("@destroyed", destroyed?)
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index e0c5725944..47e9683b44 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -290,6 +290,17 @@ class PersistenceTest < ActiveRecord::TestCase
assert_equal "The First Topic", Topic.find(copy.id).title
end
+ def test_becomes_wont_break_mutation_tracking
+ topic = topics(:first)
+ reply = topic.becomes(Reply)
+
+ assert_equal 1, topic.id_in_database
+ assert_empty topic.attributes_in_database
+
+ assert_equal 1, reply.id_in_database
+ assert_empty reply.attributes_in_database
+ end
+
def test_becomes_includes_changed_attributes
company = Company.new(name: "37signals")
client = company.becomes(Client)
diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb
index fa50eeb6a4..2e386d7669 100644
--- a/activerecord/test/models/topic.rb
+++ b/activerecord/test/models/topic.rb
@@ -97,7 +97,7 @@ class Topic < ActiveRecord::Base
end
def set_email_address
- unless persisted?
+ unless persisted? || will_save_change_to_author_email_address?
self.author_email_address = "test@test.com"
end
end