diff --git a/lib/ransack/adapters/active_record/context.rb b/lib/ransack/adapters/active_record/context.rb index e28fd812..e6f9f910 100644 --- a/lib/ransack/adapters/active_record/context.rb +++ b/lib/ransack/adapters/active_record/context.rb @@ -201,7 +201,12 @@ def extract_correlated_key(join_root) nil end when Arel::Nodes::And - extract_correlated_key(join_root.left) || extract_correlated_key(join_root.right) + # And may have multiple children, so we need to check all, not via left/right + join_root.children.each do |child| + key = extract_correlated_key(child) + return key if key + end + nil else # eg parent was Arel::Nodes::And and the evaluated side was one of # Arel::Nodes::Grouping or MultiTenant::TenantEnforcementClause diff --git a/spec/ransack/adapters/active_record/context_spec.rb b/spec/ransack/adapters/active_record/context_spec.rb index cd27f80b..3dfc0971 100644 --- a/spec/ransack/adapters/active_record/context_spec.rb +++ b/spec/ransack/adapters/active_record/context_spec.rb @@ -97,6 +97,25 @@ module ActiveRecord expect(search.result.to_sql).to match /.comments.\..person_id. = .people.\..id./ end + + it 'build correlated subquery for polymorphic & default_scope when predicate is not_cont_all' do + search = Search.new(Article, + g: [ + { + m: "and", + c: [ + { + a: ["recent_notes_note"], + p: "not_eq", + v: ["some_note"], + } + ] + } + ], + ) + + expect(search.result.to_sql).to include '("notes"."note" != \'some_note\')' + end end describe 'sharing context across searches' do diff --git a/spec/support/schema.rb b/spec/support/schema.rb index 02e5b4a1..1d4bd021 100644 --- a/spec/support/schema.rb +++ b/spec/support/schema.rb @@ -165,6 +165,7 @@ class Article < ApplicationRecord has_many :comments has_and_belongs_to_many :tags has_many :notes, as: :notable + has_many :recent_notes, as: :notable alias_attribute :content, :body @@ -246,6 +247,13 @@ class Note < ApplicationRecord belongs_to :notable, polymorphic: true end +class RecentNote < ApplicationRecord + self.table_name = "notes" + default_scope { where(notable_id: 1) } + + belongs_to :notable, polymorphic: true +end + class Account < ApplicationRecord belongs_to :agent_account, class_name: "Account" belongs_to :trade_account, class_name: "Account"