Skip to content

Commit

Permalink
Fix polymorphic association subquery
Browse files Browse the repository at this point in the history
  • Loading branch information
lazaronixon committed Jun 2, 2023
1 parent 48e4d99 commit aa41938
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 2 deletions.
16 changes: 16 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,3 +1,19 @@
* Fix where on association with has_one/has_many polymorphic relations.

Before:
```ruby
Treasure.where(price_estimates: PriceEstimate.all)
#=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
```

Later:
```ruby
Treasure.where(price_estimates: PriceEstimate.all)
#=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
```

*Lázaro Nixon*

* Assign auto populated columns on Active Record record creation.

Changes record creation logic to allow for the `auto_increment` column to be assigned
Expand Down
8 changes: 8 additions & 0 deletions activerecord/lib/active_record/reflection.rb
Expand Up @@ -531,6 +531,10 @@ def join_primary_key(klass = nil)
foreign_key
end

def join_primary_type
type
end

def join_foreign_key
active_record_primary_key
end
Expand Down Expand Up @@ -634,6 +638,10 @@ def polymorphic?
options[:polymorphic]
end

def polymorphic_name
active_record.polymorphic_name
end

def add_as_source(seed)
seed
end
Expand Down
Expand Up @@ -25,7 +25,10 @@ def queries
def ids
case value
when Relation
value.select_values.empty? ? value.select(primary_key) : value
relation = value
relation = relation.select(primary_key) if select_clause?
relation = relation.where(primary_type => polymorphic_name) if polymorphic_clause?
relation
when Array
value.map { |v| convert_to_id(v) }
else
Expand All @@ -37,6 +40,22 @@ def primary_key
associated_table.join_primary_key
end

def primary_type
associated_table.join_primary_type
end

def polymorphic_name
associated_table.polymorphic_name_association
end

def select_clause?
value.select_values.empty?
end

def polymorphic_clause?
primary_type && !value.where_values_hash.has_key?(primary_type)
end

def convert_to_id(value)
return primary_key.map { |pk| value.public_send(pk) } if primary_key.is_a?(Array)

Expand Down
6 changes: 5 additions & 1 deletion activerecord/lib/active_record/table_metadata.rb
Expand Up @@ -2,7 +2,7 @@

module ActiveRecord
class TableMetadata # :nodoc:
delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection

def initialize(klass, arel_table, reflection = nil)
@klass = klass
Expand Down Expand Up @@ -63,6 +63,10 @@ def polymorphic_association?
reflection&.polymorphic?
end

def polymorphic_name_association
reflection&.polymorphic_name
end

def through_association?
reflection&.through_reflection?
end
Expand Down
5 changes: 5 additions & 0 deletions activerecord/test/cases/relation/where_test.rb
Expand Up @@ -458,6 +458,11 @@ def test_where_on_association_with_select_relation
assert_equal essays(:david_modest_proposal), essay
end

def test_where_on_association_with_collection_polymorphic_relation
treasures = Treasure.where(name: ["diamond", "emerald"], price_estimates: PriceEstimate.all)
assert_equal [treasures(:diamond)], treasures
end

def test_where_with_strong_parameters
author = authors(:david)
params = ProtectedParams.new(name: author.name)
Expand Down
4 changes: 4 additions & 0 deletions activerecord/test/fixtures/treasures.yml
Expand Up @@ -8,3 +8,7 @@ sapphire:
ruby:
name: $LABEL
looter: louis (Parrot)

emerald:
id: 1
name: $LABEL

0 comments on commit aa41938

Please sign in to comment.