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