tiny-quick-gem 0.0.1
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 +7 -0
- data/searchkick-6.1.2/CHANGELOG.md +919 -0
- data/searchkick-6.1.2/LICENSE.txt +22 -0
- data/searchkick-6.1.2/README.md +2348 -0
- data/searchkick-6.1.2/lib/searchkick/bulk_reindex_job.rb +19 -0
- data/searchkick-6.1.2/lib/searchkick/controller_runtime.rb +40 -0
- data/searchkick-6.1.2/lib/searchkick/hash_wrapper.rb +41 -0
- data/searchkick-6.1.2/lib/searchkick/index.rb +480 -0
- data/searchkick-6.1.2/lib/searchkick/index_cache.rb +30 -0
- data/searchkick-6.1.2/lib/searchkick/index_options.rb +652 -0
- data/searchkick-6.1.2/lib/searchkick/indexer.rb +43 -0
- data/searchkick-6.1.2/lib/searchkick/log_subscriber.rb +57 -0
- data/searchkick-6.1.2/lib/searchkick/middleware.rb +19 -0
- data/searchkick-6.1.2/lib/searchkick/model.rb +120 -0
- data/searchkick-6.1.2/lib/searchkick/multi_search.rb +46 -0
- data/searchkick-6.1.2/lib/searchkick/process_batch_job.rb +20 -0
- data/searchkick-6.1.2/lib/searchkick/process_queue_job.rb +33 -0
- data/searchkick-6.1.2/lib/searchkick/query.rb +1372 -0
- data/searchkick-6.1.2/lib/searchkick/railtie.rb +7 -0
- data/searchkick-6.1.2/lib/searchkick/record_data.rb +147 -0
- data/searchkick-6.1.2/lib/searchkick/record_indexer.rb +174 -0
- data/searchkick-6.1.2/lib/searchkick/reindex_queue.rb +57 -0
- data/searchkick-6.1.2/lib/searchkick/reindex_v2_job.rb +17 -0
- data/searchkick-6.1.2/lib/searchkick/relation.rb +728 -0
- data/searchkick-6.1.2/lib/searchkick/relation_indexer.rb +184 -0
- data/searchkick-6.1.2/lib/searchkick/reranking.rb +28 -0
- data/searchkick-6.1.2/lib/searchkick/results.rb +359 -0
- data/searchkick-6.1.2/lib/searchkick/script.rb +11 -0
- data/searchkick-6.1.2/lib/searchkick/version.rb +3 -0
- data/searchkick-6.1.2/lib/searchkick/where.rb +11 -0
- data/searchkick-6.1.2/lib/searchkick.rb +388 -0
- data/searchkick-6.1.2/lib/tasks/searchkick.rake +37 -0
- data/tiny-quick-gem.gemspec +12 -0
- metadata +73 -0
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
module Searchkick
|
|
2
|
+
class Relation
|
|
3
|
+
NO_DEFAULT_VALUE = Object.new
|
|
4
|
+
|
|
5
|
+
# note: modifying body directly is not supported
|
|
6
|
+
# and has no impact on query after being executed
|
|
7
|
+
# TODO freeze body object?
|
|
8
|
+
delegate :params, to: :query
|
|
9
|
+
delegate_missing_to :private_execute
|
|
10
|
+
|
|
11
|
+
attr_reader :model
|
|
12
|
+
alias_method :klass, :model
|
|
13
|
+
|
|
14
|
+
def initialize(model, term = "*", **options)
|
|
15
|
+
@model = model
|
|
16
|
+
@term = term
|
|
17
|
+
@options = options
|
|
18
|
+
|
|
19
|
+
# generate query to validate options
|
|
20
|
+
query if options.any?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# same as Active Record
|
|
24
|
+
def inspect
|
|
25
|
+
entries = private_execute.first(11).map!(&:inspect)
|
|
26
|
+
entries[10] = "..." if entries.size == 11
|
|
27
|
+
"#<#{self.class.name} [#{entries.join(', ')}]>"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def aggs(*args, **kwargs)
|
|
31
|
+
if args.empty? && kwargs.empty?
|
|
32
|
+
private_execute.aggs
|
|
33
|
+
else
|
|
34
|
+
clone.aggs!(*args, **kwargs)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def aggs!(*args, **kwargs)
|
|
39
|
+
check_loaded
|
|
40
|
+
aggs = {}
|
|
41
|
+
args.flatten.each do |arg|
|
|
42
|
+
if arg.is_a?(Hash)
|
|
43
|
+
aggs.merge!(arg)
|
|
44
|
+
else
|
|
45
|
+
aggs[arg] = {}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
aggs.merge!(kwargs)
|
|
49
|
+
merge_option(:aggs, aggs)
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def body(value = NO_DEFAULT_VALUE)
|
|
54
|
+
if value == NO_DEFAULT_VALUE
|
|
55
|
+
query.body
|
|
56
|
+
else
|
|
57
|
+
clone.body!(value)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def body!(value)
|
|
62
|
+
check_loaded
|
|
63
|
+
@options[:body] = value
|
|
64
|
+
self
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def body_options(value)
|
|
68
|
+
clone.body_options!(value)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def body_options!(value)
|
|
72
|
+
check_loaded
|
|
73
|
+
merge_option(:body_options, value)
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def boost(value)
|
|
78
|
+
clone.boost!(value)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def boost!(value)
|
|
82
|
+
check_loaded
|
|
83
|
+
@options[:boost] = value
|
|
84
|
+
self
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def boost_by(value)
|
|
88
|
+
clone.boost_by!(value)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def boost_by!(value)
|
|
92
|
+
check_loaded
|
|
93
|
+
if value.is_a?(Array)
|
|
94
|
+
value = value.to_h { |f| [f, {factor: 1}] }
|
|
95
|
+
elsif !value.is_a?(Hash)
|
|
96
|
+
value = {value => {factor: 1}}
|
|
97
|
+
end
|
|
98
|
+
merge_option(:boost_by, value)
|
|
99
|
+
self
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def boost_by_distance(value)
|
|
103
|
+
clone.boost_by_distance!(value)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def boost_by_distance!(value)
|
|
107
|
+
check_loaded
|
|
108
|
+
# legacy format
|
|
109
|
+
value = {value[:field] => value.except(:field)} if value[:field]
|
|
110
|
+
merge_option(:boost_by_distance, value)
|
|
111
|
+
self
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def boost_by_recency(value)
|
|
115
|
+
clone.boost_by_recency!(value)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def boost_by_recency!(value)
|
|
119
|
+
check_loaded
|
|
120
|
+
merge_option(:boost_by_recency, value)
|
|
121
|
+
self
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def boost_where(value)
|
|
125
|
+
clone.boost_where!(value)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def boost_where!(value)
|
|
129
|
+
check_loaded
|
|
130
|
+
# TODO merge duplicate fields
|
|
131
|
+
merge_option(:boost_where, value)
|
|
132
|
+
self
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def conversions(value)
|
|
136
|
+
clone.conversions!(value)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def conversions!(value)
|
|
140
|
+
check_loaded
|
|
141
|
+
@options[:conversions] = value
|
|
142
|
+
self
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def conversions_v1(value)
|
|
146
|
+
clone.conversions_v1!(value)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def conversions_v1!(value)
|
|
150
|
+
check_loaded
|
|
151
|
+
@options[:conversions_v1] = value
|
|
152
|
+
self
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def conversions_v2(value)
|
|
156
|
+
clone.conversions_v2!(value)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def conversions_v2!(value)
|
|
160
|
+
check_loaded
|
|
161
|
+
@options[:conversions_v2] = value
|
|
162
|
+
self
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def conversions_term(value)
|
|
166
|
+
clone.conversions_term!(value)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def conversions_term!(value)
|
|
170
|
+
check_loaded
|
|
171
|
+
@options[:conversions_term] = value
|
|
172
|
+
self
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def debug(value = true)
|
|
176
|
+
clone.debug!(value)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def debug!(value = true)
|
|
180
|
+
check_loaded
|
|
181
|
+
@options[:debug] = value
|
|
182
|
+
self
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def emoji(value = true)
|
|
186
|
+
clone.emoji!(value)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def emoji!(value = true)
|
|
190
|
+
check_loaded
|
|
191
|
+
@options[:emoji] = value
|
|
192
|
+
self
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def exclude(*values)
|
|
196
|
+
clone.exclude!(*values)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def exclude!(*values)
|
|
200
|
+
check_loaded
|
|
201
|
+
concat_option(:exclude, values.flatten)
|
|
202
|
+
self
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def explain(value = true)
|
|
206
|
+
clone.explain!(value)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def explain!(value = true)
|
|
210
|
+
check_loaded
|
|
211
|
+
@options[:explain] = value
|
|
212
|
+
self
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def fields(*values)
|
|
216
|
+
clone.fields!(*values)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def fields!(*values)
|
|
220
|
+
check_loaded
|
|
221
|
+
concat_option(:fields, values.flatten)
|
|
222
|
+
self
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def highlight(value)
|
|
226
|
+
clone.highlight!(value)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def highlight!(value)
|
|
230
|
+
check_loaded
|
|
231
|
+
@options[:highlight] = value
|
|
232
|
+
self
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def includes(*values)
|
|
236
|
+
clone.includes!(*values)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def includes!(*values)
|
|
240
|
+
check_loaded
|
|
241
|
+
concat_option(:includes, values.flatten)
|
|
242
|
+
self
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def index_name(*values)
|
|
246
|
+
clone.index_name!(*values)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def index_name!(*values)
|
|
250
|
+
check_loaded
|
|
251
|
+
values = values.flatten
|
|
252
|
+
if values.all? { |v| v.respond_to?(:searchkick_index) }
|
|
253
|
+
models!(*values)
|
|
254
|
+
else
|
|
255
|
+
concat_option(:index_name, values)
|
|
256
|
+
self
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def indices_boost(value)
|
|
261
|
+
clone.indices_boost!(value)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def indices_boost!(value)
|
|
265
|
+
check_loaded
|
|
266
|
+
merge_option(:indices_boost, value)
|
|
267
|
+
self
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def knn(value)
|
|
271
|
+
clone.knn!(value)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def knn!(value)
|
|
275
|
+
check_loaded
|
|
276
|
+
@options[:knn] = value
|
|
277
|
+
self
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def limit(value)
|
|
281
|
+
clone.limit!(value)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def limit!(value)
|
|
285
|
+
check_loaded
|
|
286
|
+
@options[:limit] = value
|
|
287
|
+
self
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def load(value = NO_DEFAULT_VALUE)
|
|
291
|
+
if value == NO_DEFAULT_VALUE
|
|
292
|
+
private_execute
|
|
293
|
+
self
|
|
294
|
+
else
|
|
295
|
+
clone.load!(value)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def load!(value)
|
|
300
|
+
check_loaded
|
|
301
|
+
@options[:load] = value
|
|
302
|
+
self
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def match(value)
|
|
306
|
+
clone.match!(value)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def match!(value)
|
|
310
|
+
check_loaded
|
|
311
|
+
@options[:match] = value
|
|
312
|
+
self
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def misspellings(value)
|
|
316
|
+
clone.misspellings!(value)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def misspellings!(value)
|
|
320
|
+
check_loaded
|
|
321
|
+
@options[:misspellings] = value
|
|
322
|
+
self
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def models(*values)
|
|
326
|
+
clone.models!(*values)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def models!(*values)
|
|
330
|
+
check_loaded
|
|
331
|
+
concat_option(:models, values.flatten)
|
|
332
|
+
self
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def model_includes(*values)
|
|
336
|
+
clone.model_includes!(*values)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def model_includes!(*values)
|
|
340
|
+
check_loaded
|
|
341
|
+
concat_option(:model_includes, values.flatten)
|
|
342
|
+
self
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def offset(value = NO_DEFAULT_VALUE)
|
|
346
|
+
if value == NO_DEFAULT_VALUE
|
|
347
|
+
private_execute.offset
|
|
348
|
+
else
|
|
349
|
+
clone.offset!(value)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def offset!(value)
|
|
354
|
+
check_loaded
|
|
355
|
+
@options[:offset] = value
|
|
356
|
+
self
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def opaque_id(value)
|
|
360
|
+
clone.opaque_id!(value)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def opaque_id!(value)
|
|
364
|
+
check_loaded
|
|
365
|
+
@options[:opaque_id] = value
|
|
366
|
+
self
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def operator(value)
|
|
370
|
+
clone.operator!(value)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def operator!(value)
|
|
374
|
+
check_loaded
|
|
375
|
+
@options[:operator] = value
|
|
376
|
+
self
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def order(*values)
|
|
380
|
+
clone.order!(*values)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def order!(*values)
|
|
384
|
+
check_loaded
|
|
385
|
+
concat_option(:order, values.flatten)
|
|
386
|
+
self
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def padding(value = NO_DEFAULT_VALUE)
|
|
390
|
+
if value == NO_DEFAULT_VALUE
|
|
391
|
+
private_execute.padding
|
|
392
|
+
else
|
|
393
|
+
clone.padding!(value)
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def padding!(value)
|
|
398
|
+
check_loaded
|
|
399
|
+
@options[:padding] = value
|
|
400
|
+
self
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def page(value)
|
|
404
|
+
clone.page!(value)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def page!(value)
|
|
408
|
+
check_loaded
|
|
409
|
+
@options[:page] = value
|
|
410
|
+
self
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def per_page(value = NO_DEFAULT_VALUE)
|
|
414
|
+
if value == NO_DEFAULT_VALUE
|
|
415
|
+
private_execute.per_page
|
|
416
|
+
else
|
|
417
|
+
clone.per_page!(value)
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def per(value)
|
|
422
|
+
per_page(value)
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def per_page!(value)
|
|
426
|
+
check_loaded
|
|
427
|
+
# TODO set limit?
|
|
428
|
+
@options[:per_page] = value
|
|
429
|
+
self
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def profile(value = true)
|
|
433
|
+
clone.profile!(value)
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def profile!(value = true)
|
|
437
|
+
check_loaded
|
|
438
|
+
@options[:profile] = value
|
|
439
|
+
self
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
def request_params(value)
|
|
443
|
+
clone.request_params!(value)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def request_params!(value)
|
|
447
|
+
check_loaded
|
|
448
|
+
merge_option(:request_params, value)
|
|
449
|
+
self
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def routing(value)
|
|
453
|
+
clone.routing!(value)
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def routing!(value)
|
|
457
|
+
check_loaded
|
|
458
|
+
@options[:routing] = value
|
|
459
|
+
self
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
def scope_results(value)
|
|
463
|
+
clone.scope_results!(value)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def scope_results!(value)
|
|
467
|
+
check_loaded
|
|
468
|
+
@options[:scope_results] = value
|
|
469
|
+
self
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def scroll(value = NO_DEFAULT_VALUE, &block)
|
|
473
|
+
if value == NO_DEFAULT_VALUE
|
|
474
|
+
private_execute.scroll(&block)
|
|
475
|
+
elsif block_given?
|
|
476
|
+
clone.scroll!(value).scroll(&block)
|
|
477
|
+
else
|
|
478
|
+
clone.scroll!(value)
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def scroll!(value)
|
|
483
|
+
check_loaded
|
|
484
|
+
@options[:scroll] = value
|
|
485
|
+
self
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def select(*values, &block)
|
|
489
|
+
if block_given?
|
|
490
|
+
private_execute.select(*values, &block)
|
|
491
|
+
else
|
|
492
|
+
clone.select!(*values)
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
def select!(*values)
|
|
497
|
+
check_loaded
|
|
498
|
+
concat_option(:select, values.flatten)
|
|
499
|
+
self
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def similar(value = true)
|
|
503
|
+
clone.similar!(value)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def similar!(value = true)
|
|
507
|
+
check_loaded
|
|
508
|
+
@options[:similar] = value
|
|
509
|
+
self
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
def smart_aggs(value)
|
|
513
|
+
clone.smart_aggs!(value)
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def smart_aggs!(value)
|
|
517
|
+
check_loaded
|
|
518
|
+
@options[:smart_aggs] = value
|
|
519
|
+
self
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
def suggest(value = true)
|
|
523
|
+
clone.suggest!(value)
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def suggest!(value = true)
|
|
527
|
+
check_loaded
|
|
528
|
+
@options[:suggest] = value
|
|
529
|
+
self
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def total_entries(value = NO_DEFAULT_VALUE)
|
|
533
|
+
if value == NO_DEFAULT_VALUE
|
|
534
|
+
private_execute.total_entries
|
|
535
|
+
else
|
|
536
|
+
clone.total_entries!(value)
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def total_entries!(value)
|
|
541
|
+
check_loaded
|
|
542
|
+
@options[:total_entries] = value
|
|
543
|
+
self
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def track(value = true)
|
|
547
|
+
clone.track!(value)
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
def track!(value = true)
|
|
551
|
+
check_loaded
|
|
552
|
+
@options[:track] = value
|
|
553
|
+
self
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def type(*values)
|
|
557
|
+
clone.type!(*values)
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
def type!(*values)
|
|
561
|
+
check_loaded
|
|
562
|
+
concat_option(:type, values.flatten)
|
|
563
|
+
self
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def where(value = NO_DEFAULT_VALUE)
|
|
567
|
+
if value == NO_DEFAULT_VALUE
|
|
568
|
+
Where.new(self)
|
|
569
|
+
else
|
|
570
|
+
clone.where!(value)
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def where!(value)
|
|
575
|
+
check_loaded
|
|
576
|
+
value = ensure_permitted(value)
|
|
577
|
+
if @options[:where]
|
|
578
|
+
# keep simple when possible for smart aggs
|
|
579
|
+
if !@options[:where].keys.intersect?(value.keys)
|
|
580
|
+
merge_option(:where, value)
|
|
581
|
+
elsif @options[:where][:_and].is_a?(Array)
|
|
582
|
+
merge_option(:where, {_and: @options[:where][:_and] + [value]})
|
|
583
|
+
else
|
|
584
|
+
@options[:where] = {_and: [@options[:where], value]}
|
|
585
|
+
end
|
|
586
|
+
else
|
|
587
|
+
@options[:where] = value
|
|
588
|
+
end
|
|
589
|
+
self
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
def first(value = NO_DEFAULT_VALUE)
|
|
593
|
+
result =
|
|
594
|
+
if loaded?
|
|
595
|
+
private_execute
|
|
596
|
+
else
|
|
597
|
+
limit = value == NO_DEFAULT_VALUE ? 1 : value
|
|
598
|
+
previous_limit = (@options[:limit] || @options[:per_page])&.to_i
|
|
599
|
+
if previous_limit && previous_limit < limit
|
|
600
|
+
limit = previous_limit
|
|
601
|
+
end
|
|
602
|
+
limit(limit).load
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
if value == NO_DEFAULT_VALUE
|
|
606
|
+
result.first
|
|
607
|
+
else
|
|
608
|
+
result.first(value)
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
def pluck(*keys)
|
|
613
|
+
if !loaded? && @options[:load] == false
|
|
614
|
+
select(*keys).send(:private_execute).pluck(*keys)
|
|
615
|
+
else
|
|
616
|
+
private_execute.pluck(*keys)
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
def reorder(*values)
|
|
621
|
+
clone.reorder!(*values)
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def reorder!(*values)
|
|
625
|
+
check_loaded
|
|
626
|
+
@options[:order] = values
|
|
627
|
+
self
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
def reselect(*values)
|
|
631
|
+
clone.reselect!(*values)
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
def reselect!(*values)
|
|
635
|
+
check_loaded
|
|
636
|
+
@options[:select] = values
|
|
637
|
+
self
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
def rewhere(value)
|
|
641
|
+
clone.rewhere!(value)
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
def rewhere!(value)
|
|
645
|
+
check_loaded
|
|
646
|
+
@options[:where] = ensure_permitted(value)
|
|
647
|
+
self
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def only(*keys)
|
|
651
|
+
Relation.new(@model, @term, **@options.slice(*keys))
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
def except(*keys)
|
|
655
|
+
Relation.new(@model, @term, **@options.except(*keys))
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
def loaded?
|
|
659
|
+
!@execute.nil?
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
undef_method :respond_to_missing?
|
|
663
|
+
|
|
664
|
+
def respond_to_missing?(...)
|
|
665
|
+
Results.new(nil, nil, nil).respond_to?(...) || super
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# TODO uncomment in 7.0
|
|
669
|
+
# def to_json(...)
|
|
670
|
+
# private_execute.to_a.to_json(...)
|
|
671
|
+
# end
|
|
672
|
+
|
|
673
|
+
# TODO uncomment in 7.0
|
|
674
|
+
# def as_json(...)
|
|
675
|
+
# private_execute.to_a.as_json(...)
|
|
676
|
+
# end
|
|
677
|
+
|
|
678
|
+
def to_yaml
|
|
679
|
+
private_execute.to_a.to_yaml
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
private
|
|
683
|
+
|
|
684
|
+
def private_execute
|
|
685
|
+
@execute ||= query.execute
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
def query
|
|
689
|
+
@query ||= Query.new(@model, @term, **@options)
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
def check_loaded
|
|
693
|
+
raise Error, "Relation loaded" if loaded?
|
|
694
|
+
|
|
695
|
+
# reset query since options will change
|
|
696
|
+
@query = nil
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
# provides *very* basic protection from unfiltered parameters
|
|
700
|
+
# this is not meant to be comprehensive and may be expanded in the future
|
|
701
|
+
def ensure_permitted(obj)
|
|
702
|
+
obj.to_h
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def initialize_copy(other)
|
|
706
|
+
super
|
|
707
|
+
# shallow dup and avoid updating values in-place
|
|
708
|
+
@options = @options.dup
|
|
709
|
+
@execute = nil
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def concat_option(key, value)
|
|
713
|
+
if @options[key]
|
|
714
|
+
@options[key] += value
|
|
715
|
+
else
|
|
716
|
+
@options[key] = value.to_ary
|
|
717
|
+
end
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
def merge_option(key, value)
|
|
721
|
+
if @options[key]
|
|
722
|
+
@options[key] = @options[key].merge(value)
|
|
723
|
+
else
|
|
724
|
+
@options[key] = value.to_hash
|
|
725
|
+
end
|
|
726
|
+
end
|
|
727
|
+
end
|
|
728
|
+
end
|