aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorThomas Hollstegge <thomas.hollstegge@zweitag.de>2011-09-14 17:32:31 +0200
committerThomas Hollstegge <thomas.hollstegge@zweitag.de>2012-11-17 16:45:23 +0100
commit70fa756ddb83684a05c840ff16e6b57cff5c5048 (patch)
tree1fc943f7ce52cde153754b96c299f590f51d559f /activerecord
parentee9412839b8e4f30103519c20001a12582b824b8 (diff)
downloadrails-70fa756ddb83684a05c840ff16e6b57cff5c5048.tar.gz
rails-70fa756ddb83684a05c840ff16e6b57cff5c5048.tar.bz2
rails-70fa756ddb83684a05c840ff16e6b57cff5c5048.zip
AR::Base.becomes should not change the STI type
If you want to change the STI type too, use AR::Base.becomes! instead
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/persistence.rb13
-rw-r--r--activerecord/test/cases/persistence_test.rb13
3 files changed, 31 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 4fa2dcb847..8078974b43 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,12 @@
## Rails 4.0.0 (unreleased) ##
+* Don't change STI type when calling ActiveRecord::Base#becomes, add
+ ActiveRecord::Base#becomes!
+
+ See #3023.
+
+ *Thomas Hollstegge*
+
* `#pluck` can be used on a relation with `select` clause. Fix #7551
Example:
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 8e749772a1..45f5406cc3 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -155,7 +155,18 @@ module ActiveRecord
became.instance_variable_set("@new_record", new_record?)
became.instance_variable_set("@destroyed", destroyed?)
became.instance_variable_set("@errors", errors)
- became.public_send("#{klass.inheritance_column}=", klass.name) unless self.class.descends_from_active_record?
+ became
+ end
+
+ # Wrapper around +becomes+ that also changes the instance's sti column value.
+ # This is especially useful if you want to persist the changed class in your
+ # database.
+ #
+ # Note: The old instance's sti column value will be changed too, as both objects
+ # share the same set of attributes.
+ def becomes!(klass)
+ became = becomes(klass)
+ became.public_send("#{klass.inheritance_column}=", klass.sti_name) unless self.class.descends_from_active_record?
became
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 4b938da5c4..b2609f6395 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -280,12 +280,23 @@ class PersistencesTest < ActiveRecord::TestCase
def test_update_sti_type
assert_instance_of Reply, topics(:second)
- topic = topics(:second).becomes(Topic)
+ topic = topics(:second).becomes!(Topic)
assert_instance_of Topic, topic
topic.save!
assert_instance_of Topic, Topic.find(topic.id)
end
+ def test_preserve_original_sti_type
+ reply = topics(:second)
+ assert_equal "Reply", reply.type
+
+ topic = reply.becomes(Topic)
+ assert_equal "Reply", reply.type
+
+ assert_instance_of Topic, topic
+ assert_equal "Reply", topic.type
+ end
+
def test_delete
topic = Topic.find(1)
assert_equal topic, topic.delete, 'topic.delete did not return self'