bharat_filter_engine 0.1.2 → 0.2.0
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 +12 -9
- data/README.md +1 -1
- data/Rakefile +5 -3
- data/lib/bharat_filter_engine/association_resolver.rb +18 -37
- data/lib/bharat_filter_engine/column_helper.rb +28 -0
- data/lib/bharat_filter_engine/dynamic_filter_values.rb +17 -18
- data/lib/bharat_filter_engine/engine.rb +249 -91
- data/lib/bharat_filter_engine/errors.rb +1 -1
- data/lib/bharat_filter_engine/join_tracker.rb +37 -0
- data/lib/bharat_filter_engine/rule_normalizer.rb +88 -30
- data/lib/bharat_filter_engine/search_builder.rb +48 -24
- data/lib/bharat_filter_engine/version.rb +1 -1
- data/lib/bharat_filter_engine.rb +14 -12
- data/spec/association_resolver_spec.rb +60 -41
- data/spec/dynamic_filter_values_spec.rb +161 -29
- data/spec/engine_spec.rb +1144 -538
- data/spec/join_tracker_spec.rb +70 -0
- data/spec/rule_normalizer_spec.rb +181 -32
- data/spec/same_table_join_spec.rb +199 -0
- data/spec/search_builder_spec.rb +222 -42
- data/spec/spec_helper.rb +11 -12
- metadata +14 -6
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module BharatFilterEngine
|
|
4
4
|
class Engine
|
|
5
|
-
|
|
5
|
+
NUMERIC_PATTERN = /\A[+-]?\d+(\.\d+)?\z/
|
|
6
6
|
class << self
|
|
7
|
-
|
|
8
7
|
def apply(scope:, config:, params:)
|
|
9
8
|
new(
|
|
10
9
|
scope,
|
|
@@ -16,7 +15,7 @@ module BharatFilterEngine
|
|
|
16
15
|
def filter_values(scope:, config:, params:)
|
|
17
16
|
field =
|
|
18
17
|
params[:filter_field] ||
|
|
19
|
-
params[
|
|
18
|
+
params['filter_field']
|
|
20
19
|
|
|
21
20
|
rule =
|
|
22
21
|
config[field&.to_sym]
|
|
@@ -33,25 +32,35 @@ module BharatFilterEngine
|
|
|
33
32
|
rule[:dbcolumn].to_s
|
|
34
33
|
end
|
|
35
34
|
|
|
35
|
+
term =
|
|
36
|
+
params[:filter_term] ||
|
|
37
|
+
params['filter_term']
|
|
38
|
+
|
|
39
|
+
limit =
|
|
40
|
+
params[:filter_limit] ||
|
|
41
|
+
params['filter_limit']
|
|
42
|
+
|
|
36
43
|
DynamicFilterValues.new(
|
|
37
44
|
scope: scope,
|
|
38
|
-
field: field_name
|
|
45
|
+
field: field_name,
|
|
46
|
+
term: term,
|
|
47
|
+
limit: limit
|
|
39
48
|
).call || []
|
|
40
49
|
end
|
|
41
|
-
|
|
42
50
|
end
|
|
43
51
|
|
|
44
52
|
def initialize(scope, config = {}, params = {})
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
@scope = scope
|
|
54
|
+
@config = config || {}
|
|
55
|
+
@params = normalize_params(params)
|
|
48
56
|
end
|
|
49
57
|
|
|
50
58
|
def call
|
|
51
59
|
scope = @scope
|
|
60
|
+
@tracker = JoinTracker.new(scope.klass)
|
|
61
|
+
@subquery_groups = {}
|
|
52
62
|
|
|
53
63
|
@config.each do |key, raw_rule|
|
|
54
|
-
|
|
55
64
|
value =
|
|
56
65
|
@params[key.to_sym]
|
|
57
66
|
|
|
@@ -70,6 +79,10 @@ module BharatFilterEngine
|
|
|
70
79
|
)
|
|
71
80
|
end
|
|
72
81
|
|
|
82
|
+
@subquery_groups.each_value do |group|
|
|
83
|
+
scope = apply_subquery_group(scope, group)
|
|
84
|
+
end
|
|
85
|
+
|
|
73
86
|
scope
|
|
74
87
|
end
|
|
75
88
|
|
|
@@ -104,7 +117,25 @@ module BharatFilterEngine
|
|
|
104
117
|
association
|
|
105
118
|
)
|
|
106
119
|
|
|
107
|
-
|
|
120
|
+
unless result
|
|
121
|
+
raise InvalidAssociationError,
|
|
122
|
+
'BharatFilterEngine: could not resolve association ' \
|
|
123
|
+
"#{association.inspect} configured for filter " \
|
|
124
|
+
"#{rule[:dbcolumn].inspect}. Check the `association:` key " \
|
|
125
|
+
'in your filter config.'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if @tracker.claim(result) == :subquery
|
|
129
|
+
group =
|
|
130
|
+
(@subquery_groups[result[:associations]] ||= {
|
|
131
|
+
result: result,
|
|
132
|
+
entries: []
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
group[:entries] << [rule, value]
|
|
136
|
+
|
|
137
|
+
return scope
|
|
138
|
+
end
|
|
108
139
|
|
|
109
140
|
joined_scope =
|
|
110
141
|
resolver.join(
|
|
@@ -116,17 +147,37 @@ module BharatFilterEngine
|
|
|
116
147
|
joined_scope,
|
|
117
148
|
rule,
|
|
118
149
|
value,
|
|
119
|
-
table_name: result[:table_name]
|
|
150
|
+
table_name: result[:table_name],
|
|
151
|
+
klass: result[:klass]
|
|
120
152
|
).distinct
|
|
121
153
|
end
|
|
122
154
|
|
|
155
|
+
def apply_subquery_group(scope, group)
|
|
156
|
+
result = group[:result]
|
|
157
|
+
|
|
158
|
+
subquery =
|
|
159
|
+
AssociationResolver.new(scope).subquery(result[:associations]) do |relation|
|
|
160
|
+
group[:entries].reduce(relation) do |current, (rule, value)|
|
|
161
|
+
apply_filter_by_type(
|
|
162
|
+
current,
|
|
163
|
+
rule,
|
|
164
|
+
value,
|
|
165
|
+
table_name: result[:table_name],
|
|
166
|
+
klass: result[:klass]
|
|
167
|
+
)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
scope.where(scope.klass.primary_key => subquery)
|
|
172
|
+
end
|
|
173
|
+
|
|
123
174
|
def apply_filter_by_type(
|
|
124
175
|
scope,
|
|
125
176
|
rule,
|
|
126
177
|
value,
|
|
127
|
-
table_name: nil
|
|
178
|
+
table_name: nil,
|
|
179
|
+
klass: nil
|
|
128
180
|
)
|
|
129
|
-
|
|
130
181
|
column =
|
|
131
182
|
rule[:dbcolumn]
|
|
132
183
|
|
|
@@ -137,7 +188,8 @@ module BharatFilterEngine
|
|
|
137
188
|
scope,
|
|
138
189
|
column,
|
|
139
190
|
value,
|
|
140
|
-
table_name
|
|
191
|
+
table_name,
|
|
192
|
+
negate: rule[:negate]
|
|
141
193
|
)
|
|
142
194
|
|
|
143
195
|
when :boolean
|
|
@@ -145,14 +197,16 @@ module BharatFilterEngine
|
|
|
145
197
|
scope,
|
|
146
198
|
column,
|
|
147
199
|
value,
|
|
148
|
-
table_name
|
|
200
|
+
table_name,
|
|
201
|
+
negate: rule[:negate]
|
|
149
202
|
)
|
|
150
203
|
|
|
151
204
|
when :integer
|
|
152
205
|
apply_numeric_filter(
|
|
153
206
|
scope,
|
|
154
207
|
rule,
|
|
155
|
-
value
|
|
208
|
+
value,
|
|
209
|
+
:to_i,
|
|
156
210
|
table_name: table_name
|
|
157
211
|
)
|
|
158
212
|
|
|
@@ -160,7 +214,8 @@ module BharatFilterEngine
|
|
|
160
214
|
apply_numeric_filter(
|
|
161
215
|
scope,
|
|
162
216
|
rule,
|
|
163
|
-
value
|
|
217
|
+
value,
|
|
218
|
+
:to_f,
|
|
164
219
|
table_name: table_name
|
|
165
220
|
)
|
|
166
221
|
|
|
@@ -169,7 +224,8 @@ module BharatFilterEngine
|
|
|
169
224
|
scope,
|
|
170
225
|
column,
|
|
171
226
|
value,
|
|
172
|
-
table_name
|
|
227
|
+
table_name,
|
|
228
|
+
negate: rule[:negate]
|
|
173
229
|
)
|
|
174
230
|
|
|
175
231
|
when :daterange
|
|
@@ -180,10 +236,20 @@ module BharatFilterEngine
|
|
|
180
236
|
table_name: table_name
|
|
181
237
|
)
|
|
182
238
|
|
|
239
|
+
when :presence
|
|
240
|
+
apply_presence_filter(
|
|
241
|
+
scope,
|
|
242
|
+
column,
|
|
243
|
+
value,
|
|
244
|
+
table_name,
|
|
245
|
+
klass: klass
|
|
246
|
+
)
|
|
247
|
+
|
|
183
248
|
when :search
|
|
184
249
|
SearchBuilder.new(
|
|
185
250
|
scope: scope,
|
|
186
|
-
allowed_columns: rule[:dbcolumns]
|
|
251
|
+
allowed_columns: rule[:dbcolumns],
|
|
252
|
+
tracker: @tracker
|
|
187
253
|
).apply(value)
|
|
188
254
|
|
|
189
255
|
else
|
|
@@ -195,14 +261,15 @@ module BharatFilterEngine
|
|
|
195
261
|
scope,
|
|
196
262
|
column,
|
|
197
263
|
value,
|
|
198
|
-
table_name
|
|
264
|
+
table_name,
|
|
265
|
+
negate: false
|
|
199
266
|
)
|
|
200
|
-
|
|
201
267
|
apply_condition(
|
|
202
268
|
scope,
|
|
203
269
|
column,
|
|
204
270
|
Array(value),
|
|
205
|
-
table_name
|
|
271
|
+
table_name,
|
|
272
|
+
negate: negate
|
|
206
273
|
)
|
|
207
274
|
end
|
|
208
275
|
|
|
@@ -210,19 +277,20 @@ module BharatFilterEngine
|
|
|
210
277
|
scope,
|
|
211
278
|
column,
|
|
212
279
|
value,
|
|
213
|
-
table_name
|
|
280
|
+
table_name,
|
|
281
|
+
negate: false
|
|
214
282
|
)
|
|
215
|
-
|
|
216
283
|
cast_value =
|
|
217
284
|
ActiveModel::Type::Boolean
|
|
218
|
-
|
|
219
|
-
|
|
285
|
+
.new
|
|
286
|
+
.cast(value)
|
|
220
287
|
|
|
221
288
|
apply_condition(
|
|
222
289
|
scope,
|
|
223
290
|
column,
|
|
224
291
|
cast_value,
|
|
225
|
-
table_name
|
|
292
|
+
table_name,
|
|
293
|
+
negate: negate
|
|
226
294
|
)
|
|
227
295
|
end
|
|
228
296
|
|
|
@@ -230,41 +298,82 @@ module BharatFilterEngine
|
|
|
230
298
|
scope,
|
|
231
299
|
column,
|
|
232
300
|
value,
|
|
233
|
-
table_name
|
|
301
|
+
table_name,
|
|
302
|
+
negate: false
|
|
234
303
|
)
|
|
235
|
-
|
|
236
304
|
apply_condition(
|
|
237
305
|
scope,
|
|
238
306
|
column,
|
|
239
307
|
value,
|
|
240
|
-
table_name
|
|
308
|
+
table_name,
|
|
309
|
+
negate: negate
|
|
241
310
|
)
|
|
242
311
|
end
|
|
243
312
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
313
|
+
def apply_presence_filter(scope, column, value, table_name, klass: nil)
|
|
314
|
+
present = ActiveModel::Type::Boolean.new.cast(value)
|
|
315
|
+
klass ||= scope.klass
|
|
316
|
+
arel_column =
|
|
317
|
+
if table_name
|
|
318
|
+
Arel::Table.new(table_name)[column]
|
|
319
|
+
else
|
|
320
|
+
klass.arel_table[column]
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
if present
|
|
324
|
+
scope.where(ColumnHelper.present_predicate(arel_column, klass, column))
|
|
254
325
|
else
|
|
255
|
-
scope.where(
|
|
256
|
-
|
|
326
|
+
scope.where(ColumnHelper.blank_predicate(arel_column, klass, column))
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def apply_condition(scope, column, value, table_name, negate: false)
|
|
331
|
+
if negate && value.is_a?(Array)
|
|
332
|
+
return apply_negated_array_condition(
|
|
333
|
+
scope,
|
|
334
|
+
column,
|
|
335
|
+
value,
|
|
336
|
+
table_name
|
|
257
337
|
)
|
|
258
338
|
end
|
|
339
|
+
|
|
340
|
+
condition =
|
|
341
|
+
if table_name
|
|
342
|
+
{ table_name => { column => value } }
|
|
343
|
+
else
|
|
344
|
+
{ column => value }
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
negate ? scope.where.not(condition) : scope.where(condition)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def apply_negated_array_condition(scope, column, values, table_name)
|
|
351
|
+
arel_column =
|
|
352
|
+
if table_name
|
|
353
|
+
Arel::Table.new(table_name)[column]
|
|
354
|
+
else
|
|
355
|
+
scope.klass.arel_table[column]
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
membership = arel_column.in(values.compact)
|
|
359
|
+
|
|
360
|
+
predicate =
|
|
361
|
+
if values.include?(nil)
|
|
362
|
+
arel_column.eq(nil).or(membership)
|
|
363
|
+
else
|
|
364
|
+
membership
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
scope.where(Arel::Nodes::Not.new(predicate))
|
|
259
368
|
end
|
|
260
369
|
|
|
261
370
|
def apply_numeric_filter(
|
|
262
371
|
scope,
|
|
263
372
|
rule,
|
|
264
373
|
value,
|
|
374
|
+
caster,
|
|
265
375
|
table_name: nil
|
|
266
376
|
)
|
|
267
|
-
|
|
268
377
|
column =
|
|
269
378
|
rule[:dbcolumn]
|
|
270
379
|
|
|
@@ -278,36 +387,80 @@ module BharatFilterEngine
|
|
|
278
387
|
case rule[:range_type]
|
|
279
388
|
|
|
280
389
|
when :gte
|
|
390
|
+
return scope unless numeric_string?(value)
|
|
281
391
|
|
|
282
|
-
scope.where(
|
|
283
|
-
"#{qualified_column} >= ?",
|
|
284
|
-
value
|
|
285
|
-
)
|
|
392
|
+
scope.where("#{qualified_column} >= ?", cast_numeric(value, caster))
|
|
286
393
|
|
|
287
394
|
when :lte
|
|
395
|
+
return scope unless numeric_string?(value)
|
|
288
396
|
|
|
289
|
-
scope.where(
|
|
290
|
-
|
|
291
|
-
|
|
397
|
+
scope.where("#{qualified_column} <= ?", cast_numeric(value, caster))
|
|
398
|
+
|
|
399
|
+
when :between
|
|
400
|
+
apply_numeric_between(
|
|
401
|
+
scope,
|
|
402
|
+
qualified_column,
|
|
403
|
+
value,
|
|
404
|
+
caster
|
|
292
405
|
)
|
|
293
406
|
|
|
294
407
|
else
|
|
408
|
+
return scope unless numeric_string?(value)
|
|
409
|
+
|
|
295
410
|
apply_condition(
|
|
296
411
|
scope,
|
|
297
412
|
column,
|
|
298
|
-
value,
|
|
299
|
-
table_name
|
|
413
|
+
cast_numeric(value, caster),
|
|
414
|
+
table_name,
|
|
415
|
+
negate: rule[:negate]
|
|
300
416
|
)
|
|
301
417
|
end
|
|
302
418
|
end
|
|
303
419
|
|
|
420
|
+
def apply_numeric_between(scope, qualified_column, value, caster)
|
|
421
|
+
return scope unless value.present?
|
|
422
|
+
|
|
423
|
+
raw_from, raw_to =
|
|
424
|
+
extract_bounds(value)
|
|
425
|
+
|
|
426
|
+
return scope unless
|
|
427
|
+
raw_from.present? || raw_to.present?
|
|
428
|
+
|
|
429
|
+
if raw_from.present? && numeric_string?(raw_from)
|
|
430
|
+
from =
|
|
431
|
+
cast_numeric(raw_from, caster)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
if raw_to.present? && numeric_string?(raw_to)
|
|
435
|
+
to =
|
|
436
|
+
cast_numeric(raw_to, caster)
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
return scope unless from || to
|
|
440
|
+
|
|
441
|
+
if from && to
|
|
442
|
+
scope.where(qualified_column => from..to)
|
|
443
|
+
elsif from
|
|
444
|
+
scope.where("#{qualified_column} >= ?", from)
|
|
445
|
+
else
|
|
446
|
+
scope.where("#{qualified_column} <= ?", to)
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
def numeric_string?(value)
|
|
451
|
+
value.to_s.strip.match?(NUMERIC_PATTERN)
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def cast_numeric(value, caster)
|
|
455
|
+
value.to_s.public_send(caster)
|
|
456
|
+
end
|
|
457
|
+
|
|
304
458
|
def apply_date_range_filter(
|
|
305
459
|
scope,
|
|
306
460
|
rule,
|
|
307
461
|
value,
|
|
308
462
|
table_name: nil
|
|
309
463
|
)
|
|
310
|
-
|
|
311
464
|
return scope unless value.present?
|
|
312
465
|
|
|
313
466
|
column =
|
|
@@ -320,42 +473,27 @@ module BharatFilterEngine
|
|
|
320
473
|
column.to_s
|
|
321
474
|
end
|
|
322
475
|
|
|
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
|
|
476
|
+
raw_from, raw_to =
|
|
477
|
+
extract_bounds(value)
|
|
344
478
|
|
|
345
479
|
return scope unless
|
|
346
|
-
|
|
480
|
+
raw_from.present? || raw_to.present?
|
|
347
481
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
482
|
+
if raw_from.present?
|
|
483
|
+
from =
|
|
484
|
+
normalize_date(
|
|
485
|
+
raw_from,
|
|
486
|
+
:start
|
|
487
|
+
)
|
|
488
|
+
end
|
|
353
489
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
490
|
+
if raw_to.present?
|
|
491
|
+
to =
|
|
492
|
+
normalize_date(
|
|
493
|
+
raw_to,
|
|
494
|
+
:end
|
|
495
|
+
)
|
|
496
|
+
end
|
|
359
497
|
|
|
360
498
|
if from.present? && to.present?
|
|
361
499
|
|
|
@@ -379,6 +517,28 @@ module BharatFilterEngine
|
|
|
379
517
|
end
|
|
380
518
|
end
|
|
381
519
|
|
|
520
|
+
def extract_bounds(value)
|
|
521
|
+
case value
|
|
522
|
+
|
|
523
|
+
when Hash
|
|
524
|
+
[
|
|
525
|
+
value[:from] || value['from'],
|
|
526
|
+
value[:to] || value['to']
|
|
527
|
+
]
|
|
528
|
+
|
|
529
|
+
when Array
|
|
530
|
+
value
|
|
531
|
+
|
|
532
|
+
when String
|
|
533
|
+
value
|
|
534
|
+
.split(',')
|
|
535
|
+
.map(&:strip)
|
|
536
|
+
|
|
537
|
+
else
|
|
538
|
+
[nil, nil]
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
|
|
382
542
|
def normalize_date(value, boundary)
|
|
383
543
|
return value if
|
|
384
544
|
value.is_a?(Time) ||
|
|
@@ -404,13 +564,11 @@ module BharatFilterEngine
|
|
|
404
564
|
|
|
405
565
|
def deep_normalize_params(params)
|
|
406
566
|
params.transform_values do |value|
|
|
407
|
-
|
|
408
567
|
if value.is_a?(Hash)
|
|
409
568
|
deep_normalize_params(value)
|
|
410
569
|
else
|
|
411
570
|
normalize_value(value)
|
|
412
571
|
end
|
|
413
|
-
|
|
414
572
|
end
|
|
415
573
|
end
|
|
416
574
|
|
|
@@ -421,17 +579,17 @@ module BharatFilterEngine
|
|
|
421
579
|
stripped =
|
|
422
580
|
value.strip
|
|
423
581
|
|
|
424
|
-
if stripped.start_with?(
|
|
582
|
+
if stripped.start_with?('[')
|
|
425
583
|
begin
|
|
426
584
|
JSON.parse(stripped)
|
|
427
585
|
rescue JSON::ParserError
|
|
428
586
|
value
|
|
429
587
|
end
|
|
430
588
|
|
|
431
|
-
elsif value.include?(
|
|
589
|
+
elsif value.include?(',')
|
|
432
590
|
|
|
433
591
|
value
|
|
434
|
-
.split(
|
|
592
|
+
.split(',')
|
|
435
593
|
.map(&:strip)
|
|
436
594
|
|
|
437
595
|
else
|
|
@@ -440,4 +598,4 @@ module BharatFilterEngine
|
|
|
440
598
|
end
|
|
441
599
|
end
|
|
442
600
|
end
|
|
443
|
-
end
|
|
601
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'set'
|
|
4
|
+
|
|
5
|
+
module BharatFilterEngine
|
|
6
|
+
class JoinTracker
|
|
7
|
+
def initialize(base_klass)
|
|
8
|
+
@tables = Set.new([base_klass.table_name])
|
|
9
|
+
@chains = Set.new
|
|
10
|
+
@subquery_supported = base_klass.primary_key.is_a?(String)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Returns :join or :subquery.
|
|
14
|
+
def claim(result)
|
|
15
|
+
chain = result[:associations]
|
|
16
|
+
|
|
17
|
+
return :join if chain.blank?
|
|
18
|
+
return :join if @chains.include?(chain)
|
|
19
|
+
return :join unless @subquery_supported
|
|
20
|
+
return :subquery if @tables.include?(result[:table_name])
|
|
21
|
+
|
|
22
|
+
register(result)
|
|
23
|
+
:join
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def register(result)
|
|
29
|
+
chain = result[:associations]
|
|
30
|
+
|
|
31
|
+
chain.each_index do |index|
|
|
32
|
+
@chains << chain[0..index]
|
|
33
|
+
@tables << result[:reflections][index].klass.table_name
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|