1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Use polymorphic_class_for over constantize

This commit fixes 2 cases where `constantize` was used instead of
of calling `polymorphic_class_for` to retrieve the class associated
with a given string for polymorphic `belongs_to`.
This commit is contained in:
Jimmy Bourassa 2021-09-01 10:18:55 -04:00
parent e1f90a30a2
commit 2ea5ff9e13
No known key found for this signature in database
GPG key ID: 0451204015141D45
4 changed files with 53 additions and 2 deletions

View file

@ -1,3 +1,12 @@
* Fix 2 cases that inferred polymorphic class from the association's `foreign_type`
using `String#constantize` instead of the model's `polymorphic_class_for`.
When updating a polymorphic association, the old `foreign_type` was not inferred correctly when:
1. `touch`ing the previously associated record
2. updating the previously associated record's `counter_cache`
*Jimmy Bourassa*
* Add config option for ignoring tables when dumping the schema cache. * Add config option for ignoring tables when dumping the schema cache.
Applications can now be configured to ignore certain tables when dumping the schema cache. Applications can now be configured to ignore certain tables when dumping the schema cache.

View file

@ -55,7 +55,8 @@ module ActiveRecord
def decrement_counters_before_last_save def decrement_counters_before_last_save
if reflection.polymorphic? if reflection.polymorphic?
model_was = owner.attribute_before_last_save(reflection.foreign_type)&.constantize model_type_was = owner.attribute_before_last_save(reflection.foreign_type)
model_was = owner.class.polymorphic_class_for(model_type_was) if model_type_was
else else
model_was = klass model_was = klass
end end

View file

@ -49,7 +49,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
if reflection.polymorphic? if reflection.polymorphic?
foreign_type = reflection.foreign_type foreign_type = reflection.foreign_type
klass = changes[foreign_type] && changes[foreign_type].first || o.public_send(foreign_type) klass = changes[foreign_type] && changes[foreign_type].first || o.public_send(foreign_type)
klass = klass.constantize klass = o.class.polymorphic_class_for(klass)
else else
klass = association.klass klass = association.klass
end end

View file

@ -1331,6 +1331,47 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal groucho, sponsor.thing assert_equal groucho, sponsor.thing
end end
class WheelPolymorphicName < ActiveRecord::Base
self.table_name = "wheels"
belongs_to :wheelable, polymorphic: true, counter_cache: :wheels_count, touch: :wheels_owned_at
def self.polymorphic_class_for(name)
raise "Unexpected name: #{name}" unless name == "polymorphic_car"
CarPolymorphicName
end
end
class CarPolymorphicName < ActiveRecord::Base
self.table_name = "cars"
has_many :wheels, as: :wheelable
def self.polymorphic_name
"polymorphic_car"
end
end
def test_polymorphic_with_custom_name_counter_cache
car = CarPolymorphicName.create!
wheel = WheelPolymorphicName.create!(wheelable_type: "polymorphic_car", wheelable_id: car.id)
assert_equal 1, car.reload.wheels_count
wheel.update! wheelable: nil
assert_equal 0, car.reload.wheels_count
end
def test_polymorphic_with_custom_name_touch_old_belongs_to_model
car = CarPolymorphicName.create!
wheel = WheelPolymorphicName.create!(wheelable: car)
touch_time = 1.day.ago.round
travel_to(touch_time) do
wheel.update!(wheelable: nil)
end
assert_equal touch_time, car.reload.wheels_owned_at
end
def test_build_with_conditions def test_build_with_conditions
client = companies(:second_client) client = companies(:second_client)
firm = client.build_bob_firm firm = client.build_bob_firm