From 7c5be0d12b7801538e4db25d4de28a71d0665ef9 Mon Sep 17 00:00:00 2001 From: QuentinRoadstr Date: Tue, 30 Nov 2021 17:36:11 +0100 Subject: [PATCH] evol:use and for distinct keys and or for the same keys --- lib/rails_admin/adapters/active_record.rb | 12 +++++++++--- lib/rails_admin/adapters/mongoid.rb | 11 +++++++---- spec/integration/actions/index_spec.rb | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/rails_admin/adapters/active_record.rb b/lib/rails_admin/adapters/active_record.rb index 384e3221d7..376ddf226e 100644 --- a/lib/rails_admin/adapters/active_record.rb +++ b/lib/rails_admin/adapters/active_record.rb @@ -144,15 +144,21 @@ def query_scope(scope, query, fields = config.list.fields.select(&:queryable?)) # "0055" is the filter index, no use here. o is the operator, v the value def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable?)) filters.each_pair do |field_name, filters_dump| + field = fields.detect { |f| f.name.to_s == field_name } + multiple_filters_with_same_key = field.searchable_columns.length == 1 + + wb = WhereBuilder.new(scope) if multiple_filters_with_same_key + filters_dump.each do |_, filter_dump| - wb = WhereBuilder.new(scope) - field = fields.detect { |f| f.name.to_s == field_name } + wb = WhereBuilder.new(scope) unless multiple_filters_with_same_key value = parse_field_value(field, filter_dump[:v]) wb.add(field, value, (filter_dump[:o] || RailsAdmin::Config.default_search_operator)) # AND current filter statements to other filter statements - scope = wb.build + scope = wb.build unless multiple_filters_with_same_key end + # OR current filter statements to other filter statements if multiple filters for the same key + scope = wb.build if multiple_filters_with_same_key end scope end diff --git a/lib/rails_admin/adapters/mongoid.rb b/lib/rails_admin/adapters/mongoid.rb index 2e65417a07..f807b08001 100644 --- a/lib/rails_admin/adapters/mongoid.rb +++ b/lib/rails_admin/adapters/mongoid.rb @@ -147,11 +147,12 @@ def query_scope(scope, query, fields = config.list.fields.select(&:queryable?)) # filters example => {"string_field"=>{"0055"=>{"o"=>"like", "v"=>"test_value"}}, ...} # "0055" is the filter index, no use here. o is the operator, v the value def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable?)) - statements = [] + filters.each_pair do |field_name, filters_dump| + statements = [] + field = fields.detect { |f| f.name.to_s == field_name } filters_dump.each do |_, filter_dump| - field = fields.detect { |f| f.name.to_s == field_name } next unless field value = parse_field_value(field, filter_dump[:v]) @@ -163,9 +164,11 @@ def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable statements << field_statements.first end end + and_or_or = '$and' + and_or_or = '$or' if statements.length > 1 and field.searchable_columns.length == 1 + scope = scope.where(statements.any? ? {and_or_or => statements} : {}) end - - scope.where(statements.any? ? {'$and' => statements} : {}) + scope end def parse_collection_name(column) diff --git a/spec/integration/actions/index_spec.rb b/spec/integration/actions/index_spec.rb index e3d4a79c90..e3a139d126 100644 --- a/spec/integration/actions/index_spec.rb +++ b/spec/integration/actions/index_spec.rb @@ -76,6 +76,24 @@ end end + it 'allows to query the same attribute with or' do + RailsAdmin.config Player do + list do + field :name + field :team + field :injured + field :retired + end + end + + visit index_path(model_name: 'player', f: {name: {'1' => {v: @players[0].name}, '2' => {v: @players[1].name}}}) + is_expected.to have_content(@players[0].name) + is_expected.to have_content(@players[1].name) + (2..3).each do |i| + is_expected.to have_no_content(@players[i].name) + end + end + it 'allows to filter on one attribute' do RailsAdmin.config Player do list do