Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/ransack/predicate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def initialize(opts = {})
@type = opts[:type]
@formatter = opts[:formatter]
@validator = opts[:validator] ||
lambda { |v| v.respond_to?(:empty?) ? !v.empty? : !v.nil? }
lambda { |v| v.is_a?(String) || (v.respond_to?(:empty?) ? !v.empty? : !v.nil?) }
@compound = opts[:compound]
@wants_array = opts.fetch(:wants_array,
@compound || Constants::IN_NOT_IN.include?(@arel_predicate))
Expand Down
7 changes: 6 additions & 1 deletion lib/ransack/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ def initialize(object, params = {}, options = {})
if params.is_a? Hash
params = params.dup
params = params.transform_values { |v| v.is_a?(String) && strip_whitespace ? v.strip : v }
params.delete_if { |k, v| [*v].all?{ |i| i.blank? && i != false } }
params.delete_if { |k, v|
[*v].all? do |i|
i.nil? ||
(i.respond_to?(:blank?) && i.blank? && !i.is_a?(String) && i != false)
end
}
else
params = {}
end
Expand Down
56 changes: 52 additions & 4 deletions spec/ransack/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Ransack
describe Search do
describe '#initialize' do
it 'removes empty conditions before building' do
expect_any_instance_of(Search).to receive(:build).with({})
expect_any_instance_of(Search).to receive(:build).with({ 'name_eq' => '' })
Search.new(Person, name_eq: '')
end

Expand Down Expand Up @@ -58,8 +58,8 @@ module Ransack
end
end

it 'removes empty suffixed conditions before building' do
expect_any_instance_of(Search).to receive(:build).with({})
it 'keeps empty suffixed conditions before building' do
expect_any_instance_of(Search).to receive(:build).with({ 'name_eq_any' => [''] })
Search.new(Person, name_eq_any: [''])
end

Expand Down Expand Up @@ -184,12 +184,60 @@ module Ransack
expect(s.result.to_sql).to include 'published'
end

it 'discards empty conditions' do
it 'does not discard conditions with empty string values' do
s = Search.new(Person, children_name_eq: '')
condition = s.base[:children_name_eq]
expect(condition).not_to be_nil
expect(condition.values.first.value).to eq('')
end

it 'discards nil conditions' do
s = Search.new(Person, children_name_eq: nil)
condition = s.base[:children_name_eq]
expect(condition).to be_nil
end

it 'should not discard conditions with empty string values in arrays' do
s = Search.new(Person, name_in: ['', 'John'])
condition = s.base[:name_in]
expect(condition).not_to be_nil
expect(condition.values.map(&:value)).to eq(['', 'John'])
end

it 'should not discard eq conditions with empty string values' do
s = Search.new(Person, name_eq: '')
condition = s.base[:name_eq]
expect(condition).not_to be_nil
expect(condition.values.first.value).to eq('')
end

context 'issue: empty string values in predicates' do
it 'includes empty strings in IN predicates alongside other values' do
s = Search.new(Person, name_in: ['', 'John', 'Jane'])
condition = s.base[:name_in]
expect(condition).not_to be_nil
expect(condition.values.map(&:value)).to eq(['', 'John', 'Jane'])
end

it 'creates condition for eq predicate with empty string' do
s = Search.new(Person, name_eq: '')
condition = s.base[:name_eq]
expect(condition).not_to be_nil
expect(condition.values.first.value).to eq('')
end

it 'handles mixed predicates with empty strings and regular values' do
s = Search.new(Person, name_eq: '', email_eq: '[email protected]')
name_condition = s.base[:name_eq]
email_condition = s.base[:email_eq]

expect(name_condition).not_to be_nil
expect(name_condition.values.first.value).to eq('')
expect(email_condition).not_to be_nil
expect(email_condition.values.first.value).to eq('[email protected]')
end
end

it 'accepts base grouping condition as an option' do
expect(Nodes::Grouping).to receive(:new).with(kind_of(Context), 'or')
Search.new(Person, {}, { grouping: 'or' })
Expand Down
Loading