diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index cc1a505446c06..a5d2e93170d49 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Allow to save records with polymorphic join tables that have inverse of specified. + + *Markus Doits* + * Make Float distinguish between `float4` and `float8` in PostgreSQL. Fixes #52742 diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index 50ebb7ca32354..7b8e000842e09 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -93,7 +93,13 @@ def build_record(attributes) @through_scope = scope record = super - inverse = source_reflection.inverse_of + inverse = + if source_reflection.polymorphic? + source_reflection.polymorphic_inverse_of(record.class) + else + source_reflection.inverse_of + end + if inverse if inverse.collection? record.send(inverse.name) << build_through_record(record) diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index c83c3b697b671..a1381f182f0fa 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -38,6 +38,9 @@ require "models/session" require "models/sharded" require "models/cpk" +require "models/zine" +require "models/interest" +require "models/human" class HasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :posts, :readers, :people, :comments, :authors, :categories, :taggings, :tags, @@ -1320,6 +1323,15 @@ def test_has_many_through_with_polymorphic_source assert_equal [tags(:general)], post.reload.tags end + def test_has_many_through_with_polymorhic_join_model + zine = Zine.create! + + assert_nothing_raised { zine.polymorphic_humans.build.save! } + + assert_equal 1, zine.polymorphic_humans.count + assert_equal 1, zine.interests.count + end + def test_has_many_through_obeys_order_on_through_association owner = owners(:blackbeard) assert_includes owner.toys.to_sql, "pets.name desc" diff --git a/activerecord/test/models/zine.rb b/activerecord/test/models/zine.rb index 6f361665efc7a..5d4e226267e96 100644 --- a/activerecord/test/models/zine.rb +++ b/activerecord/test/models/zine.rb @@ -2,4 +2,5 @@ class Zine < ActiveRecord::Base has_many :interests, inverse_of: :zine + has_many :polymorphic_humans, through: :interests, source_type: "Human" end