Skip to content
This repository
Browse code

Merge pull request #12646 from severin/polymorphic_belongs_to_touch

polymorphic belongs_to association with touch: true updates old record correctly
Conflicts:

	activerecord/CHANGELOG.md
	activerecord/lib/active_record/associations/builder/belongs_to.rb
  • Loading branch information...
commit 04636989bec7f06bec5c9617125ca7b8dd3ba16a 1 parent 3f70d32
Yves Senn senny authored
14 activerecord/CHANGELOG.md
Source Rendered
... ... @@ -1,3 +1,17 @@
  1 +* Polymorphic belongs_to associations with the `touch: true` option set update the timestamps of
  2 + the old and new owner correctly when moved between owners of different types.
  3 +
  4 + Example:
  5 +
  6 + class Rating < ActiveRecord::Base
  7 + belongs_to :rateable, polymorphic: true, touch: true
  8 + end
  9 +
  10 + rating = Rating.create rateable: Song.find(1)
  11 + rating.update_attributes rateable: Book.find(2) # => timestamps of Song(1) and Book(2) are updated
  12 +
  13 + *Severin Schoepke*
  14 +
1 15 * Fix `last` with `offset` to return the proper record instead of always the last one.
2 16
3 17 Example:
8 activerecord/lib/active_record/associations/builder/belongs_to.rb
@@ -73,7 +73,13 @@ def belongs_to_touch_after_save_or_destroy_for_#{name}
73 73 old_foreign_id = changed_attributes[foreign_key_field]
74 74
75 75 if old_foreign_id
76   - klass = association(#{name.inspect}).klass
  76 + association = association(:#{name})
  77 + reflection = association.reflection
  78 + if reflection.polymorphic?
  79 + klass = send("#{reflection.foreign_type}_was").constantize
  80 + else
  81 + klass = association.klass
  82 + end
77 83 old_record = klass.find_by(klass.primary_key => old_foreign_id)
78 84
79 85 if old_record
58 activerecord/test/cases/timestamp_test.rb
@@ -224,36 +224,62 @@ def self.name; 'Toy'; end
224 224 assert_not_equal time, old_pet.updated_at
225 225 end
226 226
227   - def test_changing_parent_of_a_record_touches_both_new_and_old_polymorphic_parent_record
228   - klass = Class.new(ActiveRecord::Base) do
229   - def self.name; 'Toy'; end
  227 + def test_changing_parent_of_a_record_touches_both_new_and_old_polymorphic_parent_record_changes_within_same_class
  228 + car_class = Class.new(ActiveRecord::Base) do
  229 + def self.name; 'Car'; end
230 230 end
231 231
232   - wheel_klass = Class.new(ActiveRecord::Base) do
  232 + wheel_class = Class.new(ActiveRecord::Base) do
233 233 def self.name; 'Wheel'; end
234 234 belongs_to :wheelable, :polymorphic => true, :touch => true
235 235 end
236 236
237   - toy1 = klass.find(1)
238   - toy2 = klass.find(2)
  237 + car1 = car_class.find(1)
  238 + car2 = car_class.find(2)
239 239
240   - wheel = wheel_klass.new
241   - wheel.wheelable = toy1
242   - wheel.save!
  240 + wheel = wheel_class.create!(wheelable: car1)
243 241
244 242 time = 3.days.ago.at_beginning_of_hour
245 243
246   - toy1.update_columns(updated_at: time)
247   - toy2.update_columns(updated_at: time)
  244 + car1.update_columns(updated_at: time)
  245 + car2.update_columns(updated_at: time)
248 246
249   - wheel.wheelable = toy2
  247 + wheel.wheelable = car2
250 248 wheel.save!
251 249
252   - toy1.reload
253   - toy2.reload
  250 + assert_not_equal time, car1.reload.updated_at
  251 + assert_not_equal time, car2.reload.updated_at
  252 + end
  253 +
  254 + def test_changing_parent_of_a_record_touches_both_new_and_old_polymorphic_parent_record_changes_with_other_class
  255 + car_class = Class.new(ActiveRecord::Base) do
  256 + def self.name; 'Car'; end
  257 + end
  258 +
  259 + toy_class = Class.new(ActiveRecord::Base) do
  260 + def self.name; 'Toy'; end
  261 + end
  262 +
  263 + wheel_class = Class.new(ActiveRecord::Base) do
  264 + def self.name; 'Wheel'; end
  265 + belongs_to :wheelable, :polymorphic => true, :touch => true
  266 + end
  267 +
  268 + car = car_class.find(1)
  269 + toy = toy_class.find(3)
  270 +
  271 + wheel = wheel_class.create!(wheelable: car)
  272 +
  273 + time = 3.days.ago.at_beginning_of_hour
  274 +
  275 + car.update_columns(updated_at: time)
  276 + toy.update_columns(updated_at: time)
  277 +
  278 + wheel.wheelable = toy
  279 + wheel.save!
254 280
255   - assert_not_equal time, toy1.updated_at
256   - assert_not_equal time, toy2.updated_at
  281 + assert_not_equal time, car.reload.updated_at
  282 + assert_not_equal time, toy.reload.updated_at
257 283 end
258 284
259 285 def test_clearing_association_touches_the_old_record

0 comments on commit 0463698

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