diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index d2bb967600f57..fdb6c75405b4c 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -84,10 +84,17 @@ def expand_from_hash(attributes) end klass ||= AssociationQueryValue - queries = klass.new(associated_table, value).queries.map do |query| - expand_from_hash(query).reduce(&:and) + queries = klass.new(associated_table, value).queries.map! do |query| + expand_from_hash(query) + end + + if queries.one? + queries.first + else + queries.map! { |query| query.reduce(&:and) } + queries = queries.reduce { |result, query| Arel::Nodes::Or.new(result, query) } + Arel::Nodes::Grouping.new(queries) end - queries.reduce(&:or) elsif table.aggregated_with?(key) mapping = table.reflect_on_aggregation(key).mapping values = value.nil? ? [nil] : Array.wrap(value) diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 1ec349aa73487..eb677413904d3 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -110,7 +110,7 @@ def test_join_association_conditions_support_string_and_arel_expressions def test_join_conditions_allow_nil_associations authors = Author.includes(:essays).where(essays: { id: nil }) - assert_equal 2, authors.count + assert_equal 1, authors.count end def test_find_with_implicit_inner_joins_without_select_does_not_imply_readonly diff --git a/activerecord/test/cases/relation/where_chain_test.rb b/activerecord/test/cases/relation/where_chain_test.rb index 991efa649ca05..d5debc1d0488b 100644 --- a/activerecord/test/cases/relation/where_chain_test.rb +++ b/activerecord/test/cases/relation/where_chain_test.rb @@ -3,18 +3,14 @@ require "cases/helper" require "models/post" require "models/author" +require "models/essay" require "models/comment" require "models/categorization" module ActiveRecord class WhereChainTest < ActiveRecord::TestCase - fixtures :posts, :authors - - def setup - super - @name = "title" - end + fixtures :posts, :authors, :essays def test_missing_with_association assert posts(:authorless).author.blank? @@ -40,7 +36,7 @@ def test_not_with_nil end def test_association_not_eq - expected = Comment.arel_table[@name].not_eq(Arel::Nodes::BindParam.new(1)) + expected = Comment.arel_table["title"].not_eq(Arel::Nodes::BindParam.new(1)) relation = Post.joins(:comments).where.not(comments: { title: "hello" }) assert_equal(expected.to_sql, relation.where_clause.ast.to_sql) end @@ -93,6 +89,13 @@ def test_rewhere_with_one_overwriting_condition_and_one_unrelated assert_equal expected.where_clause, relation.where_clause end + def test_rewhere_with_polymorphic_association + relation = Essay.where(writer: authors(:david)).rewhere(writer_id: "Mary") + expected = Essay.where(writer: authors(:mary)) + + assert_equal expected, relation + end + def test_rewhere_with_range relation = Post.where(comments_count: 1..3).rewhere(comments_count: 3..5) diff --git a/activerecord/test/fixtures/essays.yml b/activerecord/test/fixtures/essays.yml index 9d15d82359d62..542e37f811c2c 100644 --- a/activerecord/test/fixtures/essays.yml +++ b/activerecord/test/fixtures/essays.yml @@ -4,3 +4,8 @@ david_modest_proposal: writer_id: David category_id: General author_id: David + +mary_stay_home: + name: Stay Home + writer_type: Author + writer_id: Mary