From 53f6d91f8dd0aa27cecbd114cbe3bf8b1debcff5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 06:51:29 +0000 Subject: [PATCH 1/2] Initial plan From 700668561c1ccea2b9d478225b54529cb597501a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 07:01:27 +0000 Subject: [PATCH 2/2] Implement fix for strip_whitespace not working with group conditions Co-authored-by: scarroll32 <11340230+scarroll32@users.noreply.github.com> --- lib/ransack/context.rb | 2 +- lib/ransack/nodes/grouping.rb | 14 ++++++++++++++ lib/ransack/search.rb | 1 + spec/ransack/search_spec.rb | 30 ++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/ransack/context.rb b/lib/ransack/context.rb index a55ef2735..f70297dcf 100644 --- a/lib/ransack/context.rb +++ b/lib/ransack/context.rb @@ -3,7 +3,7 @@ module Ransack class Context attr_reader :search, :object, :klass, :base, :engine, :arel_visitor - attr_accessor :auth_object, :search_key + attr_accessor :auth_object, :search_key, :strip_whitespace attr_reader :arel_visitor class << self diff --git a/lib/ransack/nodes/grouping.rb b/lib/ransack/nodes/grouping.rb index 916ee8b32..d0f5b44db 100644 --- a/lib/ransack/nodes/grouping.rb +++ b/lib/ransack/nodes/grouping.rb @@ -147,6 +147,7 @@ def new_grouping(params = {}) end def build(params) + params = strip_whitespace_from_params(params) if @context.strip_whitespace params.with_indifferent_access.each do |key, value| case key when /^(g|c|m)$/ @@ -201,6 +202,19 @@ def remove_duplicate_conditions! c.values.map { |v| v.value } end end + + def strip_whitespace_from_params(params) + case params + when Hash + params.transform_values { |v| strip_whitespace_from_params(v) } + when Array + params.map { |v| strip_whitespace_from_params(v) } + when String + params.strip + else + params + end + end end end end diff --git a/lib/ransack/search.rb b/lib/ransack/search.rb index 03115c5ac..adb1dd3ba 100644 --- a/lib/ransack/search.rb +++ b/lib/ransack/search.rb @@ -32,6 +32,7 @@ def initialize(object, params = {}, options = {}) end @context = options[:context] || Context.for(object, options) @context.auth_object = options[:auth_object] + @context.strip_whitespace = strip_whitespace @base = Nodes::Grouping.new( @context, options[:grouping] || Constants::AND ) diff --git a/spec/ransack/search_spec.rb b/spec/ransack/search_spec.rb index 9d4d9f797..6a23315e9 100644 --- a/spec/ransack/search_spec.rb +++ b/spec/ransack/search_spec.rb @@ -56,6 +56,36 @@ module Ransack .with({ 'name_eq' => ' foobar ' }) Search.new(Person, { name_eq: ' foobar ' }, { strip_whitespace: false }) end + + context 'with group conditions' do + it 'strips leading & trailing whitespace from group condition values when strip_whitespace is true' do + search = Person.ransack({g: [{name_cont: " John ", email_cont: " john@example.com ", m: "or"}]}, { strip_whitespace: true }) + + # Access the base grouping to inspect conditions + grouping = search.base.groupings.first + + # Check that whitespace was stripped from the values + name_condition = grouping.conditions.find { |c| c.predicate.name == "cont" && c.attributes.first.name == "name" } + email_condition = grouping.conditions.find { |c| c.predicate.name == "cont" && c.attributes.first.name == "email" } + + expect(name_condition.values.first.value).to eq("John") # Should be stripped + expect(email_condition.values.first.value).to eq("john@example.com") # Should be stripped + end + + it 'does not strip whitespace from group condition values when strip_whitespace is false' do + search = Person.ransack({g: [{name_cont: " John ", email_cont: " john@example.com ", m: "or"}]}, { strip_whitespace: false }) + + # Access the base grouping to inspect conditions + grouping = search.base.groupings.first + + # Check that whitespace was NOT stripped from the values + name_condition = grouping.conditions.find { |c| c.predicate.name == "cont" && c.attributes.first.name == "name" } + email_condition = grouping.conditions.find { |c| c.predicate.name == "cont" && c.attributes.first.name == "email" } + + expect(name_condition.values.first.value).to eq(" John ") # Should NOT be stripped + expect(email_condition.values.first.value).to eq(" john@example.com ") # Should NOT be stripped + end + end end it 'removes empty suffixed conditions before building' do