aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-01-29 08:34:33 +0900
committerRyuta Kamizono <kamipo@gmail.com>2018-01-29 09:24:14 +0900
commit159b21b59dba120e58eeb8bff89b9d322e720c44 (patch)
tree4961855b5e5d01f0dd9332869f94539b81422caa /activerecord
parent6b8c161fc2cabdadd33826d21f9bd099041b8069 (diff)
downloadrails-159b21b59dba120e58eeb8bff89b9d322e720c44.tar.gz
rails-159b21b59dba120e58eeb8bff89b9d322e720c44.tar.bz2
rails-159b21b59dba120e58eeb8bff89b9d322e720c44.zip
Fix expanding an array of `composed_of` objects which have multiple mappings
Follow up of #31724. If `composed_of` objects have multiple mappings, array predicate handler can not correctly handle the expanded condition. We need to handle it like polymorphic association objects.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb12
-rw-r--r--activerecord/lib/active_record/relation/where_clause_factory.rb1
-rw-r--r--activerecord/lib/active_record/table_metadata.rb8
-rw-r--r--activerecord/test/cases/finder_test.rb9
-rw-r--r--activerecord/test/fixtures/customers.yml11
5 files changed, 35 insertions, 6 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 885c26d7aa..f3286846d2 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -86,6 +86,18 @@ module ActiveRecord
expand_from_hash(query).reduce(&:and)
end
queries.reduce(&:or)
+ elsif table.aggregated_with?(key)
+ mapping = table.reflect_on_aggregation(key).mapping
+ queries = Array.wrap(value).map do |object|
+ mapping.map do |field_attr, aggregate_attr|
+ if mapping.size == 1 && !object.respond_to?(aggregate_attr)
+ build(table.arel_attribute(field_attr), object)
+ else
+ build(table.arel_attribute(field_attr), object.send(aggregate_attr))
+ end
+ end.reduce(&:and)
+ end
+ queries.reduce(&:or)
# FIXME: Deprecate this and provide a public API to force equality
elsif (value.is_a?(Range) || value.is_a?(Array)) &&
table.type(key.to_s).respond_to?(:subtype)
diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb
index 4ae94f4bfe..92b720068c 100644
--- a/activerecord/lib/active_record/relation/where_clause_factory.rb
+++ b/activerecord/lib/active_record/relation/where_clause_factory.rb
@@ -14,7 +14,6 @@ module ActiveRecord
parts = [klass.sanitize_sql(other.empty? ? opts : ([opts] + other))]
when Hash
attributes = predicate_builder.resolve_column_aliases(opts)
- attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
attributes.stringify_keys!
parts = predicate_builder.build_from_hash(attributes)
diff --git a/activerecord/lib/active_record/table_metadata.rb b/activerecord/lib/active_record/table_metadata.rb
index 0459cbdc59..507f08a974 100644
--- a/activerecord/lib/active_record/table_metadata.rb
+++ b/activerecord/lib/active_record/table_metadata.rb
@@ -65,6 +65,14 @@ module ActiveRecord
association && association.polymorphic?
end
+ def aggregated_with?(aggregation_name)
+ klass && reflect_on_aggregation(aggregation_name)
+ end
+
+ def reflect_on_aggregation(aggregation_name)
+ klass.reflect_on_aggregation(aggregation_name)
+ end
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index fabfc4574c..b413212e26 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -868,13 +868,14 @@ class FinderTest < ActiveRecord::TestCase
assert_equal customers(:david), found_customer
end
- def test_hash_condition_find_with_aggregate_having_three_mapping_array
+ def test_hash_condition_find_with_aggregate_having_three_mappings_array
david_address = customers(:david).address
zaphod_address = customers(:zaphod).address
+ barney_address = customers(:barney).address
assert_kind_of Address, david_address
assert_kind_of Address, zaphod_address
- found_customers = Customer.where(address: [david_address, zaphod_address])
- assert_equal [customers(:david), customers(:zaphod)], found_customers
+ found_customers = Customer.where(address: [david_address, zaphod_address, barney_address])
+ assert_equal [customers(:david), customers(:zaphod), customers(:barney)], found_customers.sort_by(&:id)
end
def test_hash_condition_find_with_aggregate_having_one_mapping_array
@@ -883,7 +884,7 @@ class FinderTest < ActiveRecord::TestCase
assert_kind_of Money, david_balance
assert_kind_of Money, zaphod_balance
found_customers = Customer.where(balance: [david_balance, zaphod_balance])
- assert_equal [customers(:david), customers(:zaphod)], found_customers
+ assert_equal [customers(:david), customers(:zaphod)], found_customers.sort_by(&:id)
end
def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_aggregate
diff --git a/activerecord/test/fixtures/customers.yml b/activerecord/test/fixtures/customers.yml
index 0399ff83b9..7d6c1366d0 100644
--- a/activerecord/test/fixtures/customers.yml
+++ b/activerecord/test/fixtures/customers.yml
@@ -23,4 +23,13 @@ barney:
address_street: Quiet Road
address_city: Peaceful Town
address_country: Tranquil Land
- gps_location: NULL \ No newline at end of file
+ gps_location: NULL
+
+mary:
+ id: 4
+ name: Mary
+ balance: 1
+ address_street: Funny Street
+ address_city: Peaceful Town
+ address_country: Nation Land
+ gps_location: NULL