Skip to content

Commit 5dd4dcb

Browse files
authored
Merge pull request rails#48362 from lazaronixon/fix-polymorphic-subquery
Fix polymorphic association subquery
2 parents 48e4d99 + aa41938 commit 5dd4dcb

File tree

6 files changed

+58
-2
lines changed

6 files changed

+58
-2
lines changed

activerecord/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
* Fix where on association with has_one/has_many polymorphic relations.
2+
3+
Before:
4+
```ruby
5+
Treasure.where(price_estimates: PriceEstimate.all)
6+
#=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
7+
```
8+
9+
Later:
10+
```ruby
11+
Treasure.where(price_estimates: PriceEstimate.all)
12+
#=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
13+
```
14+
15+
*Lázaro Nixon*
16+
117
* Assign auto populated columns on Active Record record creation.
218

319
Changes record creation logic to allow for the `auto_increment` column to be assigned

activerecord/lib/active_record/reflection.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,10 @@ def join_primary_key(klass = nil)
531531
foreign_key
532532
end
533533

534+
def join_primary_type
535+
type
536+
end
537+
534538
def join_foreign_key
535539
active_record_primary_key
536540
end
@@ -634,6 +638,10 @@ def polymorphic?
634638
options[:polymorphic]
635639
end
636640

641+
def polymorphic_name
642+
active_record.polymorphic_name
643+
end
644+
637645
def add_as_source(seed)
638646
seed
639647
end

activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ def queries
2525
def ids
2626
case value
2727
when Relation
28-
value.select_values.empty? ? value.select(primary_key) : value
28+
relation = value
29+
relation = relation.select(primary_key) if select_clause?
30+
relation = relation.where(primary_type => polymorphic_name) if polymorphic_clause?
31+
relation
2932
when Array
3033
value.map { |v| convert_to_id(v) }
3134
else
@@ -37,6 +40,22 @@ def primary_key
3740
associated_table.join_primary_key
3841
end
3942

43+
def primary_type
44+
associated_table.join_primary_type
45+
end
46+
47+
def polymorphic_name
48+
associated_table.polymorphic_name_association
49+
end
50+
51+
def select_clause?
52+
value.select_values.empty?
53+
end
54+
55+
def polymorphic_clause?
56+
primary_type && !value.where_values_hash.has_key?(primary_type)
57+
end
58+
4059
def convert_to_id(value)
4160
return primary_key.map { |pk| value.public_send(pk) } if primary_key.is_a?(Array)
4261

activerecord/lib/active_record/table_metadata.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module ActiveRecord
44
class TableMetadata # :nodoc:
5-
delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
5+
delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
66

77
def initialize(klass, arel_table, reflection = nil)
88
@klass = klass
@@ -63,6 +63,10 @@ def polymorphic_association?
6363
reflection&.polymorphic?
6464
end
6565

66+
def polymorphic_name_association
67+
reflection&.polymorphic_name
68+
end
69+
6670
def through_association?
6771
reflection&.through_reflection?
6872
end

activerecord/test/cases/relation/where_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,11 @@ def test_where_on_association_with_select_relation
458458
assert_equal essays(:david_modest_proposal), essay
459459
end
460460

461+
def test_where_on_association_with_collection_polymorphic_relation
462+
treasures = Treasure.where(name: ["diamond", "emerald"], price_estimates: PriceEstimate.all)
463+
assert_equal [treasures(:diamond)], treasures
464+
end
465+
461466
def test_where_with_strong_parameters
462467
author = authors(:david)
463468
params = ProtectedParams.new(name: author.name)

activerecord/test/fixtures/treasures.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ sapphire:
88
ruby:
99
name: $LABEL
1010
looter: louis (Parrot)
11+
12+
emerald:
13+
id: 1
14+
name: $LABEL

0 commit comments

Comments
 (0)