From 1c85a61ec7d21159524f305b8b8200ece191ca88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:05:59 +0000 Subject: [PATCH 1/4] Initial plan From f954ddf359783118793ff3dea54f635af5028066 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:13:44 +0000 Subject: [PATCH 2/4] Add failing test for top-level OR modifier issue Co-authored-by: scarroll32 <11340230+scarroll32@users.noreply.github.com> --- spec/ransack/search_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/spec/ransack/search_spec.rb b/spec/ransack/search_spec.rb index 26433199d..65f6d56db 100644 --- a/spec/ransack/search_spec.rb +++ b/spec/ransack/search_spec.rb @@ -500,6 +500,30 @@ module Ransack expect(s).to be_an ActiveRecord::Relation end + it 'should use OR combinator when m: "or" is used at top level' do + s = Search.new(Person, m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie') + + expect(s.base.combinator).to eq 'or' + + # Should generate OR query + result = s.result + expect(result.to_sql).to match /#{people_name_field} = 'Ernie' OR #{children_people_name_field} = 'Ernie'/ + end + + it 'should create conditions in base grouping with OR combinator' do + s = Search.new(Person, m: 'or', id_eq: '12', name_contains: '12') + + expect(s.base.combinator).to eq 'or' + expect(s.base.conditions.size).to eq 2 + + # Check that both conditions are in the base grouping + id_condition = s.base.conditions.find { |c| c.key.include?('id_eq') } + name_condition = s.base.conditions.find { |c| c.key.include?('name_contains') } + + expect(id_condition).not_to be_nil + expect(name_condition).not_to be_nil + end + private def remove_quotes_and_backticks(str) From 50acf1a88321547a6a597aa4fe945ceaa8afb396 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:40:45 +0000 Subject: [PATCH 3/4] Fix OR modifier not working at top level Co-authored-by: scarroll32 <11340230+scarroll32@users.noreply.github.com> --- lib/ransack/search.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ransack/search.rb b/lib/ransack/search.rb index 03115c5ac..89f5b42ad 100644 --- a/lib/ransack/search.rb +++ b/lib/ransack/search.rb @@ -49,6 +49,9 @@ def build(params) collapse_multiparameter_attributes!(params).each do |key, value| if ['s'.freeze, 'sorts'.freeze].freeze.include?(key) send("#{key}=", value) + elsif key.to_s == 'm' + # Handle combinator (m) parameter explicitly to ensure it works at top level + base.combinator = value.to_s elsif @context.ransackable_scope?(key, @context.object) add_scope(key, value) elsif base.attribute_method?(key) From 6b8c5cf52889341e3c33d169af099c9d8b3960bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:48:41 +0000 Subject: [PATCH 4/4] Add comprehensive tests for top-level OR modifier functionality Co-authored-by: scarroll32 <11340230+scarroll32@users.noreply.github.com> --- spec/ransack/search_spec.rb | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/spec/ransack/search_spec.rb b/spec/ransack/search_spec.rb index 65f6d56db..d1aac51bf 100644 --- a/spec/ransack/search_spec.rb +++ b/spec/ransack/search_spec.rb @@ -524,6 +524,56 @@ module Ransack expect(name_condition).not_to be_nil end + it 'should handle OR combinator with symbol value' do + s = Search.new(Person, m: :or, name_eq: 'John') + + expect(s.base.combinator).to eq 'or' + end + + it 'should default to AND combinator when m parameter is not specified' do + s = Search.new(Person, name_eq: 'John', id_eq: '1') + + expect(s.base.combinator).to eq 'and' + end + + it 'should not interfere with existing grouping-based OR functionality' do + s = Search.new(Person, + g: [ + { m: 'or', name_eq: 'Ernie', children_name_eq: 'Ernie' } + ] + ) + + # Base grouping should still use default AND combinator + expect(s.base.combinator).to eq 'and' + + # Sub-grouping should use OR combinator + sub_grouping = s.base.groupings.first + expect(sub_grouping).not_to be_nil + expect(sub_grouping.combinator).to eq 'or' + end + + it 'should work with combination of top-level OR and sub-groupings' do + s = Search.new(Person, + m: 'or', + name_eq: 'John', + g: [ + { m: 'and', id_eq: '1', email_cont: 'test' } + ] + ) + + # Base grouping should use OR combinator from top-level m parameter + expect(s.base.combinator).to eq 'or' + + # Sub-grouping should use AND combinator from its own m parameter + sub_grouping = s.base.groupings.first + expect(sub_grouping).not_to be_nil + expect(sub_grouping.combinator).to eq 'and' + + # Base should have both a condition and a sub-grouping + expect(s.base.conditions.size).to eq 1 + expect(s.base.groupings.size).to eq 1 + end + private def remove_quotes_and_backticks(str)