diff --git a/lib/ransack/nodes/grouping.rb b/lib/ransack/nodes/grouping.rb index 643ffd9..5f6746e 100644 --- a/lib/ransack/nodes/grouping.rb +++ b/lib/ransack/nodes/grouping.rb @@ -44,7 +44,7 @@ module Ransack self.conditions << condition if condition.valid? end end - self.conditions.uniq! + remove_duplicate_conditions! end alias :c= :conditions= @@ -195,6 +195,17 @@ module Ransack Predicate.detect_and_strip_from_string!(string) string end + + def remove_duplicate_conditions! + # If self.conditions.uniq! is called without passing a block, then + # conditions differing only by ransacker_args within attributes are + # wrongly considered equal and are removed. + self.conditions.uniq! do |c| + c.attributes.map { |a| [a.name, a.ransacker_args] }.flatten + + [c.predicate.name] + + c.values.map { |v| v.value } + end + end end end end diff --git a/spec/ransack/nodes/grouping_spec.rb b/spec/ransack/nodes/grouping_spec.rb index 27058f2..6d412c3 100644 --- a/spec/ransack/nodes/grouping_spec.rb +++ b/spec/ransack/nodes/grouping_spec.rb @@ -50,6 +50,40 @@ module Ransack end end + describe '#conditions=' do + let(:conditions) do + { + "0"=>{ + "a"=>{"0"=>{"name"=>"name", "ransacker_args"=>""}}, "p"=>"cont", "v"=>{"0"=>{"value"=>"John"}} + }, + "1"=>{ + "a"=>{"0"=>{"name"=>"name", "ransacker_args"=>""}}, "p"=>"cont", "v"=>{"0"=>{"value"=>"John"}} + } + } + end + + before { subject.conditions = conditions } + + it 'removes duplicates' do + expect(subject.conditions.count).to eq 1 + end + + context 'when conditions differ only by ransacker_args' do + let(:conditions) do + { + "0"=>{ + "a"=>{"0"=>{"name"=>"with_arguments", "ransacker_args"=>[1,2]}}, "p"=>"eq", "v"=>{"0"=>{"value"=>"10"}} + }, + "1"=>{ + "a"=>{"0"=>{"name"=>"with_arguments", "ransacker_args"=>[3,4]}}, "p"=>"eq", "v"=>{"0"=>{"value"=>"10"}} + } + } + end + it "doesn't consider them duplicates" do + expect(subject.conditions.count).to eq 2 + end + end + end end end end