Skip to content

Commit

Permalink
allow to autosave associations with polymorphic has many through join…
Browse files Browse the repository at this point in the history
… model and inverse of

Before this was not possible:

```ruby
class Zine < ActiveRecord::Base
  has_many :interests, inverse_of: :zine
  has_many :humans, through: :interests, source: :interestable, source_type: 'Human'
end

class Interest < ActiveRecord::Base
  belongs_to :zine, inverse_of: :interests
  belongs_to :interestable, polymorphic: true, inverse_of: :interests
end

class Human < ActiveRecord::Base
  has_many :interests, as: :interestable, inverse_of: :interestable
end

zine = Zine.create!
zine.humans.create!

# => ArgumentError: Polymorphic associations do not support computing the class.
```

Now the code checks wether the association is polymorphic and uses the
correct code to get the inverse association.
  • Loading branch information
doits committed Oct 4, 2024
1 parent 0df09dd commit 8ca04d4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 1 deletion.
4 changes: 4 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions activerecord/test/models/zine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

class Zine < ActiveRecord::Base
has_many :interests, inverse_of: :zine
has_many :polymorphic_humans, through: :interests, source_type: "Human"
end

0 comments on commit 8ca04d4

Please sign in to comment.