bharat_filter_engine 0.1.2 → 0.2.0pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +10 -9
- data/README.md +1 -1
- data/Rakefile +5 -3
- data/lib/bharat_filter_engine/association_resolver.rb +4 -4
- data/lib/bharat_filter_engine/dynamic_filter_values.rb +28 -12
- data/lib/bharat_filter_engine/engine.rb +211 -85
- data/lib/bharat_filter_engine/errors.rb +1 -1
- data/lib/bharat_filter_engine/rule_normalizer.rb +88 -30
- data/lib/bharat_filter_engine/search_builder.rb +34 -16
- data/lib/bharat_filter_engine/version.rb +1 -1
- data/lib/bharat_filter_engine.rb +12 -12
- data/spec/association_resolver_spec.rb +60 -41
- data/spec/dynamic_filter_values_spec.rb +121 -29
- data/spec/engine_spec.rb +1074 -540
- data/spec/rule_normalizer_spec.rb +181 -32
- data/spec/search_builder_spec.rb +178 -43
- data/spec/spec_helper.rb +7 -12
- metadata +8 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 811680608cacda9f967cd20ce13482ed5cbe637ce21193d6d7b4932266f15556
|
|
4
|
+
data.tar.gz: 41c8837e9ae4df42f83d5fae6a7907ed00dfb7308f72273dbe23d7e05f55ac03
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c61055a2cb73bd87b4ddb0bc1258515ee78d1f9dbafe51ad1027165de23b054c3a5d07bb3d3b14c6df089c6d6b34f99b565bedae8a5d05eb63f7ff31bedab5e6
|
|
7
|
+
data.tar.gz: d68e184b788757dcbb8940cb2096ce85859b6a70864457f4977a3b4607316fa7d455e078624ed5f8acc39a78f458331ef4c0bb7b7f455a6d5f4de57dd01176b1
|
data/Gemfile
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
source
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
|
-
gem
|
|
8
|
-
gem
|
|
9
|
-
gem
|
|
7
|
+
gem 'activemodel', '>= 6.1'
|
|
8
|
+
gem 'activerecord', '>= 6.1'
|
|
9
|
+
gem 'activesupport', '>= 6.1'
|
|
10
10
|
|
|
11
11
|
group :development, :test do
|
|
12
|
-
gem
|
|
13
|
-
gem
|
|
14
|
-
gem
|
|
12
|
+
gem 'rake'
|
|
13
|
+
gem 'rspec'
|
|
14
|
+
gem 'rubocop-rails-omakase', require: false
|
|
15
|
+
gem 'sqlite3'
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
group :test do
|
|
18
|
-
gem
|
|
19
|
-
end
|
|
19
|
+
gem 'database_cleaner-active_record'
|
|
20
|
+
end
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@ query string) into a filtered `ActiveRecord::Relation` — including
|
|
|
8
8
|
filters on associated models, free-text search, and dynamically
|
|
9
9
|
populated dropdown values.
|
|
10
10
|
|
|
11
|
-
[](CHANGELOG.md)
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
|
|
14
14
|
---
|
data/Rakefile
CHANGED
|
@@ -7,7 +7,7 @@ module BharatFilterEngine
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def resolve(path)
|
|
10
|
-
parts = path.to_s.split(
|
|
10
|
+
parts = path.to_s.split('__').map(&:to_sym)
|
|
11
11
|
|
|
12
12
|
return nil if parts.empty?
|
|
13
13
|
|
|
@@ -58,13 +58,13 @@ module BharatFilterEngine
|
|
|
58
58
|
# lead -> client -> name
|
|
59
59
|
# ----------------------------------------
|
|
60
60
|
|
|
61
|
-
parts = field.split(
|
|
61
|
+
parts = field.split('__')
|
|
62
62
|
|
|
63
63
|
column =
|
|
64
64
|
parts.pop
|
|
65
65
|
|
|
66
66
|
association_path =
|
|
67
|
-
parts.join(
|
|
67
|
+
parts.join('__')
|
|
68
68
|
|
|
69
69
|
result =
|
|
70
70
|
resolve(association_path)
|
|
@@ -99,4 +99,4 @@ module BharatFilterEngine
|
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
|
-
end
|
|
102
|
+
end
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module BharatFilterEngine
|
|
4
4
|
class DynamicFilterValues
|
|
5
|
-
|
|
5
|
+
LIKE_ESCAPE_CHAR = '\\'
|
|
6
|
+
|
|
7
|
+
def initialize(scope:, field:, model: nil, term: nil, limit: nil)
|
|
6
8
|
@scope = scope
|
|
7
9
|
@model = model || scope.klass
|
|
8
10
|
@field = field.to_s
|
|
11
|
+
@term = term.presence
|
|
12
|
+
@limit = limit.presence&.to_i
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
def call
|
|
@@ -20,20 +24,32 @@ module BharatFilterEngine
|
|
|
20
24
|
result[:associations]
|
|
21
25
|
)
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
arel_column = result[:klass].arel_table[result[:column]]
|
|
28
|
+
|
|
29
|
+
scoped =
|
|
30
|
+
scoped.where(
|
|
31
|
+
arel_column.not_eq(nil).and(
|
|
32
|
+
arel_column.not_eq('')
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
scoped = apply_term(scoped, arel_column) if @term
|
|
37
|
+
|
|
38
|
+
scoped = scoped.distinct.order(arel_column)
|
|
39
|
+
scoped = scoped.limit(@limit) if @limit&.positive?
|
|
40
|
+
|
|
41
|
+
scoped.pluck(arel_column)
|
|
42
|
+
end
|
|
25
43
|
|
|
26
|
-
|
|
27
|
-
nested ? { result[:table_name] => { column => [nil, ""] } } : { column => [nil, ""] }
|
|
44
|
+
private
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
def apply_term(scoped, arel_column)
|
|
47
|
+
escaped =
|
|
48
|
+
@term.to_s.gsub(/[\\%_]/) { |char| "#{LIKE_ESCAPE_CHAR}#{char}" }
|
|
31
49
|
|
|
32
|
-
scoped
|
|
33
|
-
.
|
|
34
|
-
|
|
35
|
-
.order(qualified_column)
|
|
36
|
-
.pluck(qualified_column)
|
|
50
|
+
scoped.where(
|
|
51
|
+
arel_column.matches("%#{escaped}%", LIKE_ESCAPE_CHAR)
|
|
52
|
+
)
|
|
37
53
|
end
|
|
38
54
|
end
|
|
39
55
|
end
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module BharatFilterEngine
|
|
4
4
|
class Engine
|
|
5
|
-
|
|
6
5
|
class << self
|
|
7
|
-
|
|
8
6
|
def apply(scope:, config:, params:)
|
|
9
7
|
new(
|
|
10
8
|
scope,
|
|
@@ -16,7 +14,7 @@ module BharatFilterEngine
|
|
|
16
14
|
def filter_values(scope:, config:, params:)
|
|
17
15
|
field =
|
|
18
16
|
params[:filter_field] ||
|
|
19
|
-
params[
|
|
17
|
+
params['filter_field']
|
|
20
18
|
|
|
21
19
|
rule =
|
|
22
20
|
config[field&.to_sym]
|
|
@@ -33,25 +31,33 @@ module BharatFilterEngine
|
|
|
33
31
|
rule[:dbcolumn].to_s
|
|
34
32
|
end
|
|
35
33
|
|
|
34
|
+
term =
|
|
35
|
+
params[:filter_term] ||
|
|
36
|
+
params['filter_term']
|
|
37
|
+
|
|
38
|
+
limit =
|
|
39
|
+
params[:filter_limit] ||
|
|
40
|
+
params['filter_limit']
|
|
41
|
+
|
|
36
42
|
DynamicFilterValues.new(
|
|
37
43
|
scope: scope,
|
|
38
|
-
field: field_name
|
|
44
|
+
field: field_name,
|
|
45
|
+
term: term,
|
|
46
|
+
limit: limit
|
|
39
47
|
).call || []
|
|
40
48
|
end
|
|
41
|
-
|
|
42
49
|
end
|
|
43
50
|
|
|
44
51
|
def initialize(scope, config = {}, params = {})
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
@scope = scope
|
|
53
|
+
@config = config || {}
|
|
54
|
+
@params = normalize_params(params)
|
|
48
55
|
end
|
|
49
56
|
|
|
50
57
|
def call
|
|
51
58
|
scope = @scope
|
|
52
59
|
|
|
53
60
|
@config.each do |key, raw_rule|
|
|
54
|
-
|
|
55
61
|
value =
|
|
56
62
|
@params[key.to_sym]
|
|
57
63
|
|
|
@@ -104,7 +110,13 @@ module BharatFilterEngine
|
|
|
104
110
|
association
|
|
105
111
|
)
|
|
106
112
|
|
|
107
|
-
|
|
113
|
+
unless result
|
|
114
|
+
raise InvalidAssociationError,
|
|
115
|
+
'BharatFilterEngine: could not resolve association ' \
|
|
116
|
+
"#{association.inspect} configured for filter " \
|
|
117
|
+
"#{rule[:dbcolumn].inspect}. Check the `association:` key " \
|
|
118
|
+
'in your filter config.'
|
|
119
|
+
end
|
|
108
120
|
|
|
109
121
|
joined_scope =
|
|
110
122
|
resolver.join(
|
|
@@ -126,7 +138,6 @@ module BharatFilterEngine
|
|
|
126
138
|
value,
|
|
127
139
|
table_name: nil
|
|
128
140
|
)
|
|
129
|
-
|
|
130
141
|
column =
|
|
131
142
|
rule[:dbcolumn]
|
|
132
143
|
|
|
@@ -137,7 +148,8 @@ module BharatFilterEngine
|
|
|
137
148
|
scope,
|
|
138
149
|
column,
|
|
139
150
|
value,
|
|
140
|
-
table_name
|
|
151
|
+
table_name,
|
|
152
|
+
negate: rule[:negate]
|
|
141
153
|
)
|
|
142
154
|
|
|
143
155
|
when :boolean
|
|
@@ -145,14 +157,16 @@ module BharatFilterEngine
|
|
|
145
157
|
scope,
|
|
146
158
|
column,
|
|
147
159
|
value,
|
|
148
|
-
table_name
|
|
160
|
+
table_name,
|
|
161
|
+
negate: rule[:negate]
|
|
149
162
|
)
|
|
150
163
|
|
|
151
164
|
when :integer
|
|
152
165
|
apply_numeric_filter(
|
|
153
166
|
scope,
|
|
154
167
|
rule,
|
|
155
|
-
value
|
|
168
|
+
value,
|
|
169
|
+
:to_i,
|
|
156
170
|
table_name: table_name
|
|
157
171
|
)
|
|
158
172
|
|
|
@@ -160,7 +174,8 @@ module BharatFilterEngine
|
|
|
160
174
|
apply_numeric_filter(
|
|
161
175
|
scope,
|
|
162
176
|
rule,
|
|
163
|
-
value
|
|
177
|
+
value,
|
|
178
|
+
:to_f,
|
|
164
179
|
table_name: table_name
|
|
165
180
|
)
|
|
166
181
|
|
|
@@ -169,7 +184,8 @@ module BharatFilterEngine
|
|
|
169
184
|
scope,
|
|
170
185
|
column,
|
|
171
186
|
value,
|
|
172
|
-
table_name
|
|
187
|
+
table_name,
|
|
188
|
+
negate: rule[:negate]
|
|
173
189
|
)
|
|
174
190
|
|
|
175
191
|
when :daterange
|
|
@@ -180,6 +196,14 @@ module BharatFilterEngine
|
|
|
180
196
|
table_name: table_name
|
|
181
197
|
)
|
|
182
198
|
|
|
199
|
+
when :presence
|
|
200
|
+
apply_presence_filter(
|
|
201
|
+
scope,
|
|
202
|
+
column,
|
|
203
|
+
value,
|
|
204
|
+
table_name
|
|
205
|
+
)
|
|
206
|
+
|
|
183
207
|
when :search
|
|
184
208
|
SearchBuilder.new(
|
|
185
209
|
scope: scope,
|
|
@@ -195,14 +219,15 @@ module BharatFilterEngine
|
|
|
195
219
|
scope,
|
|
196
220
|
column,
|
|
197
221
|
value,
|
|
198
|
-
table_name
|
|
222
|
+
table_name,
|
|
223
|
+
negate: false
|
|
199
224
|
)
|
|
200
|
-
|
|
201
225
|
apply_condition(
|
|
202
226
|
scope,
|
|
203
227
|
column,
|
|
204
228
|
Array(value),
|
|
205
|
-
table_name
|
|
229
|
+
table_name,
|
|
230
|
+
negate: negate
|
|
206
231
|
)
|
|
207
232
|
end
|
|
208
233
|
|
|
@@ -210,19 +235,20 @@ module BharatFilterEngine
|
|
|
210
235
|
scope,
|
|
211
236
|
column,
|
|
212
237
|
value,
|
|
213
|
-
table_name
|
|
238
|
+
table_name,
|
|
239
|
+
negate: false
|
|
214
240
|
)
|
|
215
|
-
|
|
216
241
|
cast_value =
|
|
217
242
|
ActiveModel::Type::Boolean
|
|
218
|
-
|
|
219
|
-
|
|
243
|
+
.new
|
|
244
|
+
.cast(value)
|
|
220
245
|
|
|
221
246
|
apply_condition(
|
|
222
247
|
scope,
|
|
223
248
|
column,
|
|
224
249
|
cast_value,
|
|
225
|
-
table_name
|
|
250
|
+
table_name,
|
|
251
|
+
negate: negate
|
|
226
252
|
)
|
|
227
253
|
end
|
|
228
254
|
|
|
@@ -230,41 +256,92 @@ module BharatFilterEngine
|
|
|
230
256
|
scope,
|
|
231
257
|
column,
|
|
232
258
|
value,
|
|
233
|
-
table_name
|
|
259
|
+
table_name,
|
|
260
|
+
negate: false
|
|
234
261
|
)
|
|
235
|
-
|
|
236
262
|
apply_condition(
|
|
237
263
|
scope,
|
|
238
264
|
column,
|
|
239
265
|
value,
|
|
240
|
-
table_name
|
|
266
|
+
table_name,
|
|
267
|
+
negate: negate
|
|
241
268
|
)
|
|
242
269
|
end
|
|
243
270
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
271
|
+
def apply_presence_filter(scope, column, value, table_name)
|
|
272
|
+
present = ActiveModel::Type::Boolean.new.cast(value)
|
|
273
|
+
|
|
274
|
+
arel_column =
|
|
275
|
+
if table_name
|
|
276
|
+
Arel::Table.new(table_name)[column]
|
|
277
|
+
else
|
|
278
|
+
scope.klass.arel_table[column]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
if present
|
|
249
282
|
scope.where(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
283
|
+
arel_column.not_eq(nil).and(
|
|
284
|
+
arel_column.not_eq('')
|
|
285
|
+
)
|
|
253
286
|
)
|
|
254
287
|
else
|
|
255
288
|
scope.where(
|
|
256
|
-
|
|
289
|
+
arel_column.eq(nil).or(
|
|
290
|
+
arel_column.eq('')
|
|
291
|
+
)
|
|
292
|
+
)
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def apply_condition(scope, column, value, table_name, negate: false)
|
|
297
|
+
if negate && value.is_a?(Array)
|
|
298
|
+
return apply_negated_array_condition(
|
|
299
|
+
scope,
|
|
300
|
+
column,
|
|
301
|
+
value,
|
|
302
|
+
table_name
|
|
257
303
|
)
|
|
258
304
|
end
|
|
305
|
+
|
|
306
|
+
condition =
|
|
307
|
+
if table_name
|
|
308
|
+
{ table_name => { column => value } }
|
|
309
|
+
else
|
|
310
|
+
{ column => value }
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
negate ? scope.where.not(condition) : scope.where(condition)
|
|
259
314
|
end
|
|
260
315
|
|
|
316
|
+
def apply_negated_array_condition(scope, column, values, table_name)
|
|
317
|
+
arel_column =
|
|
318
|
+
if table_name
|
|
319
|
+
Arel::Table.new(table_name)[column]
|
|
320
|
+
else
|
|
321
|
+
scope.klass.arel_table[column]
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
membership = arel_column.in(values.compact)
|
|
325
|
+
|
|
326
|
+
predicate =
|
|
327
|
+
if values.include?(nil)
|
|
328
|
+
arel_column.eq(nil).or(membership)
|
|
329
|
+
else
|
|
330
|
+
membership
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
scope.where(Arel::Nodes::Not.new(predicate))
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
NUMERIC_PATTERN = /\A[+-]?\d+(\.\d+)?\z/
|
|
337
|
+
|
|
261
338
|
def apply_numeric_filter(
|
|
262
339
|
scope,
|
|
263
340
|
rule,
|
|
264
341
|
value,
|
|
342
|
+
caster,
|
|
265
343
|
table_name: nil
|
|
266
344
|
)
|
|
267
|
-
|
|
268
345
|
column =
|
|
269
346
|
rule[:dbcolumn]
|
|
270
347
|
|
|
@@ -278,36 +355,80 @@ module BharatFilterEngine
|
|
|
278
355
|
case rule[:range_type]
|
|
279
356
|
|
|
280
357
|
when :gte
|
|
358
|
+
return scope unless numeric_string?(value)
|
|
281
359
|
|
|
282
|
-
scope.where(
|
|
283
|
-
"#{qualified_column} >= ?",
|
|
284
|
-
value
|
|
285
|
-
)
|
|
360
|
+
scope.where("#{qualified_column} >= ?", cast_numeric(value, caster))
|
|
286
361
|
|
|
287
362
|
when :lte
|
|
363
|
+
return scope unless numeric_string?(value)
|
|
288
364
|
|
|
289
|
-
scope.where(
|
|
290
|
-
|
|
291
|
-
|
|
365
|
+
scope.where("#{qualified_column} <= ?", cast_numeric(value, caster))
|
|
366
|
+
|
|
367
|
+
when :between
|
|
368
|
+
apply_numeric_between(
|
|
369
|
+
scope,
|
|
370
|
+
qualified_column,
|
|
371
|
+
value,
|
|
372
|
+
caster
|
|
292
373
|
)
|
|
293
374
|
|
|
294
375
|
else
|
|
376
|
+
return scope unless numeric_string?(value)
|
|
377
|
+
|
|
295
378
|
apply_condition(
|
|
296
379
|
scope,
|
|
297
380
|
column,
|
|
298
|
-
value,
|
|
299
|
-
table_name
|
|
381
|
+
cast_numeric(value, caster),
|
|
382
|
+
table_name,
|
|
383
|
+
negate: rule[:negate]
|
|
300
384
|
)
|
|
301
385
|
end
|
|
302
386
|
end
|
|
303
387
|
|
|
388
|
+
def apply_numeric_between(scope, qualified_column, value, caster)
|
|
389
|
+
return scope unless value.present?
|
|
390
|
+
|
|
391
|
+
raw_from, raw_to =
|
|
392
|
+
extract_bounds(value)
|
|
393
|
+
|
|
394
|
+
return scope unless
|
|
395
|
+
raw_from.present? || raw_to.present?
|
|
396
|
+
|
|
397
|
+
if raw_from.present? && numeric_string?(raw_from)
|
|
398
|
+
from =
|
|
399
|
+
cast_numeric(raw_from, caster)
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
if raw_to.present? && numeric_string?(raw_to)
|
|
403
|
+
to =
|
|
404
|
+
cast_numeric(raw_to, caster)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
return scope unless from || to
|
|
408
|
+
|
|
409
|
+
if from && to
|
|
410
|
+
scope.where(qualified_column => from..to)
|
|
411
|
+
elsif from
|
|
412
|
+
scope.where("#{qualified_column} >= ?", from)
|
|
413
|
+
else
|
|
414
|
+
scope.where("#{qualified_column} <= ?", to)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def numeric_string?(value)
|
|
419
|
+
value.to_s.strip.match?(NUMERIC_PATTERN)
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def cast_numeric(value, caster)
|
|
423
|
+
value.to_s.public_send(caster)
|
|
424
|
+
end
|
|
425
|
+
|
|
304
426
|
def apply_date_range_filter(
|
|
305
427
|
scope,
|
|
306
428
|
rule,
|
|
307
429
|
value,
|
|
308
430
|
table_name: nil
|
|
309
431
|
)
|
|
310
|
-
|
|
311
432
|
return scope unless value.present?
|
|
312
433
|
|
|
313
434
|
column =
|
|
@@ -320,42 +441,27 @@ module BharatFilterEngine
|
|
|
320
441
|
column.to_s
|
|
321
442
|
end
|
|
322
443
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
when Hash
|
|
327
|
-
[
|
|
328
|
-
value[:from] ||
|
|
329
|
-
value["from"],
|
|
330
|
-
|
|
331
|
-
value[:to] ||
|
|
332
|
-
value["to"]
|
|
333
|
-
]
|
|
334
|
-
|
|
335
|
-
when Array
|
|
336
|
-
value
|
|
337
|
-
|
|
338
|
-
when String
|
|
339
|
-
value
|
|
340
|
-
.split(",")
|
|
341
|
-
.map(&:strip)
|
|
342
|
-
|
|
343
|
-
end
|
|
444
|
+
raw_from, raw_to =
|
|
445
|
+
extract_bounds(value)
|
|
344
446
|
|
|
345
447
|
return scope unless
|
|
346
|
-
|
|
448
|
+
raw_from.present? || raw_to.present?
|
|
347
449
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
450
|
+
if raw_from.present?
|
|
451
|
+
from =
|
|
452
|
+
normalize_date(
|
|
453
|
+
raw_from,
|
|
454
|
+
:start
|
|
455
|
+
)
|
|
456
|
+
end
|
|
353
457
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
458
|
+
if raw_to.present?
|
|
459
|
+
to =
|
|
460
|
+
normalize_date(
|
|
461
|
+
raw_to,
|
|
462
|
+
:end
|
|
463
|
+
)
|
|
464
|
+
end
|
|
359
465
|
|
|
360
466
|
if from.present? && to.present?
|
|
361
467
|
|
|
@@ -379,6 +485,28 @@ module BharatFilterEngine
|
|
|
379
485
|
end
|
|
380
486
|
end
|
|
381
487
|
|
|
488
|
+
def extract_bounds(value)
|
|
489
|
+
case value
|
|
490
|
+
|
|
491
|
+
when Hash
|
|
492
|
+
[
|
|
493
|
+
value[:from] || value['from'],
|
|
494
|
+
value[:to] || value['to']
|
|
495
|
+
]
|
|
496
|
+
|
|
497
|
+
when Array
|
|
498
|
+
value
|
|
499
|
+
|
|
500
|
+
when String
|
|
501
|
+
value
|
|
502
|
+
.split(',')
|
|
503
|
+
.map(&:strip)
|
|
504
|
+
|
|
505
|
+
else
|
|
506
|
+
[nil, nil]
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
382
510
|
def normalize_date(value, boundary)
|
|
383
511
|
return value if
|
|
384
512
|
value.is_a?(Time) ||
|
|
@@ -404,13 +532,11 @@ module BharatFilterEngine
|
|
|
404
532
|
|
|
405
533
|
def deep_normalize_params(params)
|
|
406
534
|
params.transform_values do |value|
|
|
407
|
-
|
|
408
535
|
if value.is_a?(Hash)
|
|
409
536
|
deep_normalize_params(value)
|
|
410
537
|
else
|
|
411
538
|
normalize_value(value)
|
|
412
539
|
end
|
|
413
|
-
|
|
414
540
|
end
|
|
415
541
|
end
|
|
416
542
|
|
|
@@ -421,17 +547,17 @@ module BharatFilterEngine
|
|
|
421
547
|
stripped =
|
|
422
548
|
value.strip
|
|
423
549
|
|
|
424
|
-
if stripped.start_with?(
|
|
550
|
+
if stripped.start_with?('[')
|
|
425
551
|
begin
|
|
426
552
|
JSON.parse(stripped)
|
|
427
553
|
rescue JSON::ParserError
|
|
428
554
|
value
|
|
429
555
|
end
|
|
430
556
|
|
|
431
|
-
elsif value.include?(
|
|
557
|
+
elsif value.include?(',')
|
|
432
558
|
|
|
433
559
|
value
|
|
434
|
-
.split(
|
|
560
|
+
.split(',')
|
|
435
561
|
.map(&:strip)
|
|
436
562
|
|
|
437
563
|
else
|
|
@@ -440,4 +566,4 @@ module BharatFilterEngine
|
|
|
440
566
|
end
|
|
441
567
|
end
|
|
442
568
|
end
|
|
443
|
-
end
|
|
569
|
+
end
|