Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

AR::Base.becomes should not change the STI type

If you want to change the STI type too, use AR::Base.becomes! instead
  • Loading branch information...
commit 70fa756ddb83684a05c840ff16e6b57cff5c5048 1 parent ee94128
Thomas Hollstegge authored
7 activerecord/CHANGELOG.md
Source Rendered
... ... @@ -1,5 +1,12 @@
1 1 ## Rails 4.0.0 (unreleased) ##
2 2
  3 +* Don't change STI type when calling ActiveRecord::Base#becomes, add
  4 + ActiveRecord::Base#becomes!
  5 +
  6 + See #3023.
  7 +
  8 + *Thomas Hollstegge*
  9 +
3 10 * `#pluck` can be used on a relation with `select` clause. Fix #7551
4 11
5 12 Example:
13 activerecord/lib/active_record/persistence.rb
@@ -155,7 +155,18 @@ def becomes(klass)
155 155 became.instance_variable_set("@new_record", new_record?)
156 156 became.instance_variable_set("@destroyed", destroyed?)
157 157 became.instance_variable_set("@errors", errors)
158   - became.public_send("#{klass.inheritance_column}=", klass.name) unless self.class.descends_from_active_record?
  158 + became
  159 + end
  160 +
  161 + # Wrapper around +becomes+ that also changes the instance's sti column value.
  162 + # This is especially useful if you want to persist the changed class in your
  163 + # database.
  164 + #
  165 + # Note: The old instance's sti column value will be changed too, as both objects
  166 + # share the same set of attributes.
  167 + def becomes!(klass)
  168 + became = becomes(klass)
  169 + became.public_send("#{klass.inheritance_column}=", klass.sti_name) unless self.class.descends_from_active_record?
159 170 became
160 171 end
161 172
13 activerecord/test/cases/persistence_test.rb
@@ -280,12 +280,23 @@ def test_update_for_record_with_only_primary_key
280 280 def test_update_sti_type
281 281 assert_instance_of Reply, topics(:second)
282 282
283   - topic = topics(:second).becomes(Topic)
  283 + topic = topics(:second).becomes!(Topic)
284 284 assert_instance_of Topic, topic
285 285 topic.save!
286 286 assert_instance_of Topic, Topic.find(topic.id)
287 287 end
288 288
  289 + def test_preserve_original_sti_type
  290 + reply = topics(:second)
  291 + assert_equal "Reply", reply.type
  292 +
  293 + topic = reply.becomes(Topic)
  294 + assert_equal "Reply", reply.type
  295 +
  296 + assert_instance_of Topic, topic
  297 + assert_equal "Reply", topic.type
  298 + end
  299 +
289 300 def test_delete
290 301 topic = Topic.find(1)
291 302 assert_equal topic, topic.delete, 'topic.delete did not return self'

0 comments on commit 70fa756

Please sign in to comment.
Something went wrong with that request. Please try again.