mongoid 7.2.3 → 7.3.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.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +16 -0
  5. data/lib/config/locales/en.yml +2 -2
  6. data/lib/mongoid/association/accessors.rb +1 -1
  7. data/lib/mongoid/association/constrainable.rb +1 -1
  8. data/lib/mongoid/association/depending.rb +4 -4
  9. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  10. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  11. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  12. data/lib/mongoid/association/nested/many.rb +1 -1
  13. data/lib/mongoid/association/nested/one.rb +4 -2
  14. data/lib/mongoid/association/proxy.rb +6 -1
  15. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  16. data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
  17. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  19. data/lib/mongoid/attributes.rb +24 -13
  20. data/lib/mongoid/attributes/projector.rb +120 -0
  21. data/lib/mongoid/cacheable.rb +2 -2
  22. data/lib/mongoid/clients.rb +1 -1
  23. data/lib/mongoid/clients/factory.rb +22 -8
  24. data/lib/mongoid/config.rb +19 -2
  25. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  26. data/lib/mongoid/copyable.rb +1 -1
  27. data/lib/mongoid/criteria.rb +4 -5
  28. data/lib/mongoid/criteria/findable.rb +1 -1
  29. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  30. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  31. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  32. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  33. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  34. data/lib/mongoid/document.rb +1 -15
  35. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  36. data/lib/mongoid/evolvable.rb +1 -1
  37. data/lib/mongoid/extensions/boolean.rb +1 -2
  38. data/lib/mongoid/extensions/false_class.rb +1 -1
  39. data/lib/mongoid/extensions/hash.rb +2 -2
  40. data/lib/mongoid/extensions/true_class.rb +1 -1
  41. data/lib/mongoid/fields.rb +43 -5
  42. data/lib/mongoid/inspectable.rb +1 -1
  43. data/lib/mongoid/matcher.rb +7 -0
  44. data/lib/mongoid/matcher/bits.rb +41 -0
  45. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  46. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  47. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  48. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  49. data/lib/mongoid/matcher/expression.rb +4 -0
  50. data/lib/mongoid/matcher/field_operator.rb +6 -0
  51. data/lib/mongoid/matcher/mod.rb +17 -0
  52. data/lib/mongoid/matcher/type.rb +99 -0
  53. data/lib/mongoid/persistable/deletable.rb +1 -2
  54. data/lib/mongoid/persistable/destroyable.rb +8 -2
  55. data/lib/mongoid/persistable/updatable.rb +27 -2
  56. data/lib/mongoid/query_cache.rb +35 -29
  57. data/lib/mongoid/selectable.rb +5 -7
  58. data/lib/mongoid/shardable.rb +21 -5
  59. data/lib/mongoid/touchable.rb +23 -4
  60. data/lib/mongoid/version.rb +1 -1
  61. data/spec/integration/associations/embeds_many_spec.rb +44 -0
  62. data/spec/integration/associations/has_one_spec.rb +48 -0
  63. data/spec/integration/criteria/date_field_spec.rb +1 -1
  64. data/spec/integration/document_spec.rb +9 -0
  65. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  66. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  67. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  68. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  69. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  70. data/spec/integration/matcher_operator_data/in.yml +16 -0
  71. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  72. data/spec/integration/matcher_operator_data/type.yml +70 -0
  73. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  74. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  75. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  76. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  77. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  78. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  79. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  80. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  81. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  82. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  83. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  84. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  85. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  86. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  87. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  88. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  89. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  90. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  91. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  92. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  93. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  94. data/spec/lite_spec_helper.rb +2 -0
  95. data/spec/mongoid/association/depending_spec.rb +391 -352
  96. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  97. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  98. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  99. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  100. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  101. data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
  102. data/spec/mongoid/atomic/paths_spec.rb +64 -12
  103. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  104. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  105. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  106. data/spec/mongoid/attributes_spec.rb +98 -6
  107. data/spec/mongoid/clients/factory_spec.rb +48 -0
  108. data/spec/mongoid/config_spec.rb +32 -0
  109. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  110. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  111. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  112. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  113. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  114. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
  115. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  116. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  117. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  118. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  119. data/spec/mongoid/criteria_spec.rb +0 -275
  120. data/spec/mongoid/document_spec.rb +13 -13
  121. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  122. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  123. data/spec/mongoid/extensions/string_spec.rb +5 -5
  124. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  125. data/spec/mongoid/fields/localized_spec.rb +4 -4
  126. data/spec/mongoid/fields_spec.rb +4 -4
  127. data/spec/mongoid/inspectable_spec.rb +12 -4
  128. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  129. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  130. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  131. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  132. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  133. data/spec/mongoid/reloadable_spec.rb +18 -1
  134. data/spec/mongoid/shardable_spec.rb +44 -0
  135. data/spec/mongoid/touchable_spec.rb +104 -16
  136. data/spec/mongoid/touchable_spec_models.rb +52 -0
  137. data/spec/mongoid/validatable_spec.rb +1 -1
  138. data/spec/spec_helper.rb +6 -2
  139. data/spec/support/client_registry.rb +9 -0
  140. data/spec/support/models/bolt.rb +8 -0
  141. data/spec/support/models/hole.rb +13 -0
  142. data/spec/support/models/mop.rb +0 -1
  143. data/spec/support/models/nut.rb +8 -0
  144. data/spec/support/models/person.rb +6 -0
  145. data/spec/support/models/sealer.rb +8 -0
  146. data/spec/support/models/shirt.rb +12 -0
  147. data/spec/support/models/spacer.rb +8 -0
  148. data/spec/support/models/threadlocker.rb +8 -0
  149. data/spec/support/models/washer.rb +8 -0
  150. metadata +97 -3
  151. metadata.gz.sig +5 -3
  152. data/spec/support/cluster_config.rb +0 -158
@@ -0,0 +1,590 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require "spec_helper"
5
+ require_relative './selectable_shared_examples'
6
+
7
+ describe Mongoid::Criteria::Queryable::Selectable do
8
+
9
+ let(:query) do
10
+ Mongoid::Query.new("id" => "_id")
11
+ end
12
+
13
+ describe "#where" do
14
+
15
+ let(:query_method) { :where }
16
+
17
+ context "when provided no criterion" do
18
+
19
+ let(:selection) do
20
+ query.where
21
+ end
22
+
23
+ it "does not add any criterion" do
24
+ expect(selection.selector).to eq({})
25
+ end
26
+
27
+ it "returns the query" do
28
+ expect(selection).to eq(query)
29
+ end
30
+
31
+ it "returns a cloned query" do
32
+ expect(selection).to_not equal(query)
33
+ end
34
+ end
35
+
36
+ it_behaves_like 'requires a non-nil argument'
37
+
38
+ context "when provided a string" do
39
+
40
+ let(:selection) do
41
+ query.where("this.value = 10")
42
+ end
43
+
44
+ it "adds the $where criterion" do
45
+ expect(selection.selector).to eq({ "$where" => "this.value = 10" })
46
+ end
47
+
48
+ it "returns a cloned query" do
49
+ expect(selection).to_not equal(query)
50
+ end
51
+
52
+ context 'when multiple calls with string argument are made' do
53
+
54
+ let(:selection) do
55
+ query.where("this.value = 10").where('foo.bar')
56
+ end
57
+
58
+ it 'combines conditions' do
59
+ expect(selection.selector).to eq(
60
+ "$where" => "this.value = 10", '$and' => [{'$where' => 'foo.bar'}],
61
+ )
62
+ end
63
+ end
64
+
65
+ context 'when called with string argument and with hash argument' do
66
+
67
+ let(:selection) do
68
+ query.where("this.value = 10").where(foo: 'bar')
69
+ end
70
+
71
+ it 'combines conditions' do
72
+ expect(selection.selector).to eq(
73
+ "$where" => "this.value = 10", 'foo' => 'bar',
74
+ )
75
+ end
76
+ end
77
+
78
+ context 'when called with hash argument and with string argument' do
79
+
80
+ let(:selection) do
81
+ query.where(foo: 'bar').where("this.value = 10")
82
+ end
83
+
84
+ it 'combines conditions' do
85
+ expect(selection.selector).to eq(
86
+ 'foo' => 'bar', "$where" => "this.value = 10",
87
+ )
88
+ end
89
+ end
90
+
91
+ context 'when called with two hash arguments' do
92
+ context 'when arguments use operators' do
93
+ shared_examples 'combines conditions' do
94
+
95
+ it 'combines conditions' do
96
+ expect(selection.selector).to eq(
97
+ 'foo' => {'$in' => [1]},
98
+ '$and' => ['foo' => {'$in' => [2]}],
99
+ )
100
+ end
101
+ end
102
+
103
+ context 'string operators' do
104
+
105
+ let(:selection) do
106
+ query.where(foo: {'$in' => [1]}).where(foo: {'$in' => [2]})
107
+ end
108
+
109
+ include_examples 'combines conditions'
110
+ end
111
+
112
+ context 'symbol operators' do
113
+
114
+ let(:selection) do
115
+ query.where(foo: {:$in => [1]}).where(foo: {:$in => [2]})
116
+ end
117
+
118
+ include_examples 'combines conditions'
119
+ end
120
+
121
+ context 'string and symbol operators' do
122
+
123
+ let(:selection) do
124
+ query.where(foo: {'$in' => [1]}).where(foo: {:$in => [2]})
125
+ end
126
+
127
+ include_examples 'combines conditions'
128
+ end
129
+
130
+ context 'symbol and string operators' do
131
+
132
+ let(:selection) do
133
+ query.where(foo: {:$in => [1]}).where(foo: {'$in' => [2]})
134
+ end
135
+
136
+ include_examples 'combines conditions'
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ context "when provided a single criterion" do
143
+
144
+ context "when the value needs no evolution" do
145
+
146
+ let(:selection) do
147
+ query.where(name: "Syd")
148
+ end
149
+
150
+ it "adds the criterion to the selection" do
151
+ expect(selection.selector).to eq({ "name" => "Syd" })
152
+ end
153
+ end
154
+
155
+ context "when the value must be evolved" do
156
+
157
+ before(:all) do
158
+ class Document
159
+ def id
160
+ 13
161
+ end
162
+ def self.evolve(object)
163
+ object.id
164
+ end
165
+ end
166
+ end
167
+
168
+ after(:all) do
169
+ Object.send(:remove_const, :Document)
170
+ end
171
+
172
+ context "when the key needs evolution" do
173
+
174
+ let(:query) do
175
+ Mongoid::Query.new({ "user" => "user_id" })
176
+ end
177
+
178
+ let(:document) do
179
+ Document.new
180
+ end
181
+
182
+ let(:selection) do
183
+ query.where(user: document)
184
+ end
185
+
186
+ it "alters the key and value" do
187
+ expect(selection.selector).to eq({ "user_id" => document.id })
188
+ end
189
+ end
190
+
191
+ context 'when the field is a String and the value is a BSON::Regexp::Raw' do
192
+
193
+ let(:raw_regexp) do
194
+ BSON::Regexp::Raw.new('^Em')
195
+ end
196
+
197
+ let(:selection) do
198
+ Login.where(_id: raw_regexp)
199
+ end
200
+
201
+ it 'does not convert the bson raw regexp object to a String' do
202
+ expect(selection.selector).to eq({ "_id" => raw_regexp })
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ context "when provided complex criterion" do
209
+
210
+ context "when performing an $all" do
211
+
212
+ context "when performing a single query" do
213
+
214
+ let(:selection) do
215
+ query.where(:field.all => [ 1, 2 ])
216
+ end
217
+
218
+ it "adds the $all criterion" do
219
+ expect(selection.selector).to eq({ "field" => { "$all" => [ 1, 2 ] }})
220
+ end
221
+
222
+ it "returns a cloned query" do
223
+ expect(selection).to_not eq(query)
224
+ end
225
+ end
226
+ end
227
+
228
+ context "when performing an $elemMatch" do
229
+
230
+ context "when the value is not complex" do
231
+
232
+ let(:selection) do
233
+ query.where(:field.elem_match => { key: 1 })
234
+ end
235
+
236
+ it "adds the $elemMatch criterion" do
237
+ expect(selection.selector).to eq(
238
+ { "field" => { "$elemMatch" => { 'key' => 1 } }}
239
+ )
240
+ end
241
+
242
+ it "returns a cloned query" do
243
+ expect(selection).to_not eq(query)
244
+ end
245
+ end
246
+
247
+ context "when the value is complex" do
248
+
249
+ let(:selection) do
250
+ query.where(:field.elem_match => { :key.gt => 1 })
251
+ end
252
+
253
+ it "adds the $elemMatch criterion" do
254
+ expect(selection.selector).to eq(
255
+ { "field" => { "$elemMatch" => { "key" => { "$gt" => 1 }}}}
256
+ )
257
+ end
258
+
259
+ it "returns a cloned query" do
260
+ expect(selection).to_not eq(query)
261
+ end
262
+ end
263
+ end
264
+
265
+ context "when performing an $exists" do
266
+
267
+ context "when providing boolean values" do
268
+
269
+ let(:selection) do
270
+ query.where(:field.exists => true)
271
+ end
272
+
273
+ it "adds the $exists criterion" do
274
+ expect(selection.selector).to eq(
275
+ { "field" => { "$exists" => true }}
276
+ )
277
+ end
278
+
279
+ it "returns a cloned query" do
280
+ expect(selection).to_not eq(query)
281
+ end
282
+ end
283
+
284
+ context "when providing string values" do
285
+
286
+ let(:selection) do
287
+ query.where(:field.exists => "t")
288
+ end
289
+
290
+ it "adds the $exists criterion" do
291
+ expect(selection.selector).to eq(
292
+ { "field" => { "$exists" => true }}
293
+ )
294
+ end
295
+
296
+ it "returns a cloned query" do
297
+ expect(selection).to_not eq(query)
298
+ end
299
+ end
300
+ end
301
+
302
+ context "when performing a $gt" do
303
+
304
+ let(:selection) do
305
+ query.where(:field.gt => 10)
306
+ end
307
+
308
+ it "adds the $gt criterion" do
309
+ expect(selection.selector).to eq(
310
+ { "field" => { "$gt" => 10 }}
311
+ )
312
+ end
313
+
314
+ it "returns a cloned query" do
315
+ expect(selection).to_not eq(query)
316
+ end
317
+ end
318
+
319
+ context "when performing a $gte" do
320
+
321
+ let(:selection) do
322
+ query.where(:field.gte => 10)
323
+ end
324
+
325
+ it "adds the $gte criterion" do
326
+ expect(selection.selector).to eq(
327
+ { "field" => { "$gte" => 10 }}
328
+ )
329
+ end
330
+
331
+ it "returns a cloned query" do
332
+ expect(selection).to_not eq(query)
333
+ end
334
+ end
335
+
336
+ context "when performing an $in" do
337
+
338
+ let(:selection) do
339
+ query.where(:field.in => [ 1, 2 ])
340
+ end
341
+
342
+ it "adds the $in criterion" do
343
+ expect(selection.selector).to eq({ "field" => { "$in" => [ 1, 2 ] }})
344
+ end
345
+
346
+ it "returns a cloned query" do
347
+ expect(selection).to_not eq(query)
348
+ end
349
+ end
350
+
351
+ context "when performing a $lt" do
352
+
353
+ let(:selection) do
354
+ query.where(:field.lt => 10)
355
+ end
356
+
357
+ it "adds the $lt criterion" do
358
+ expect(selection.selector).to eq(
359
+ { "field" => { "$lt" => 10 }}
360
+ )
361
+ end
362
+
363
+ it "returns a cloned query" do
364
+ expect(selection).to_not eq(query)
365
+ end
366
+ end
367
+
368
+ context "when performing a $lte" do
369
+
370
+ let(:selection) do
371
+ query.where(:field.lte => 10)
372
+ end
373
+
374
+ it "adds the $lte criterion" do
375
+ expect(selection.selector).to eq(
376
+ { "field" => { "$lte" => 10 }}
377
+ )
378
+ end
379
+
380
+ it "returns a cloned query" do
381
+ expect(selection).to_not eq(query)
382
+ end
383
+ end
384
+
385
+ context "when performing a $mod" do
386
+
387
+ let(:selection) do
388
+ query.where(:field.mod => [ 10, 1 ])
389
+ end
390
+
391
+ it "adds the $lte criterion" do
392
+ expect(selection.selector).to eq(
393
+ { "field" => { "$mod" => [ 10, 1 ]}}
394
+ )
395
+ end
396
+
397
+ it "returns a cloned query" do
398
+ expect(selection).to_not eq(query)
399
+ end
400
+ end
401
+
402
+ context "when performing a $ne" do
403
+
404
+ let(:selection) do
405
+ query.where(:field.ne => 10)
406
+ end
407
+
408
+ it "adds the $ne criterion" do
409
+ expect(selection.selector).to eq(
410
+ { "field" => { "$ne" => 10 }}
411
+ )
412
+ end
413
+
414
+ it "returns a cloned query" do
415
+ expect(selection).to_not eq(query)
416
+ end
417
+ end
418
+
419
+ context "when performing a $near" do
420
+
421
+ let(:selection) do
422
+ query.where(:field.near => [ 1, 1 ])
423
+ end
424
+
425
+ it "adds the $near criterion" do
426
+ expect(selection.selector).to eq(
427
+ { "field" => { "$near" => [ 1, 1 ] }}
428
+ )
429
+ end
430
+
431
+ it "returns a cloned query" do
432
+ expect(selection).to_not eq(query)
433
+ end
434
+ end
435
+
436
+ context "when performing a $nearSphere" do
437
+
438
+ let(:selection) do
439
+ query.where(:field.near_sphere => [ 1, 1 ])
440
+ end
441
+
442
+ it "adds the $nearSphere criterion" do
443
+ expect(selection.selector).to eq(
444
+ { "field" => { "$nearSphere" => [ 1, 1 ] }}
445
+ )
446
+ end
447
+
448
+ it "returns a cloned query" do
449
+ expect(selection).to_not eq(query)
450
+ end
451
+ end
452
+
453
+ context "when performing a $nin" do
454
+
455
+ let(:selection) do
456
+ query.where(:field.nin => [ 1, 2 ])
457
+ end
458
+
459
+ it "adds the $nin criterion" do
460
+ expect(selection.selector).to eq({ "field" => { "$nin" => [ 1, 2 ] }})
461
+ end
462
+
463
+ it "returns a cloned query" do
464
+ expect(selection).to_not eq(query)
465
+ end
466
+ end
467
+
468
+ context "when performing a $not" do
469
+
470
+ let(:selection) do
471
+ query.where(:field.not => /test/)
472
+ end
473
+
474
+ it "adds the $not criterion" do
475
+ expect(selection.selector).to eq({ "field" => { "$not" => /test/ }})
476
+ end
477
+
478
+ it "returns a cloned query" do
479
+ expect(selection).to_not eq(query)
480
+ end
481
+ end
482
+
483
+ context "when performing a $size" do
484
+
485
+ context "when providing an integer" do
486
+
487
+ let(:selection) do
488
+ query.where(:field.with_size => 10)
489
+ end
490
+
491
+ it "adds the $size criterion" do
492
+ expect(selection.selector).to eq(
493
+ { "field" => { "$size" => 10 }}
494
+ )
495
+ end
496
+
497
+ it "returns a cloned query" do
498
+ expect(selection).to_not eq(query)
499
+ end
500
+ end
501
+
502
+ context "when providing a string" do
503
+
504
+ let(:selection) do
505
+ query.where(:field.with_size => "10")
506
+ end
507
+
508
+ it "adds the $size criterion" do
509
+ expect(selection.selector).to eq(
510
+ { "field" => { "$size" => 10 }}
511
+ )
512
+ end
513
+
514
+ it "returns a cloned query" do
515
+ expect(selection).to_not eq(query)
516
+ end
517
+ end
518
+ end
519
+
520
+ context "when performing a $type" do
521
+
522
+ let(:selection) do
523
+ query.where(:field.with_type => 10)
524
+ end
525
+
526
+ it "adds the $type criterion" do
527
+ expect(selection.selector).to eq(
528
+ { "field" => { "$type" => 10 }}
529
+ )
530
+ end
531
+
532
+ it "returns a cloned query" do
533
+ expect(selection).to_not eq(query)
534
+ end
535
+ end
536
+ end
537
+
538
+ context 'when using an MQL logical operator manually' do
539
+ let(:base_query) do
540
+ query.where(test: 1)
541
+ end
542
+
543
+ let(:selection) do
544
+ base_query.where(mql_operator => ['hello' => 'world'])
545
+ end
546
+
547
+ shared_examples_for 'adds conditions to existing query' do
548
+ it 'adds conditions to existing query' do
549
+ selection.selector.should == {
550
+ 'test' => 1,
551
+ mql_operator => ['hello' => 'world'],
552
+ }
553
+ end
554
+ end
555
+
556
+ shared_examples_for 'adds conditions to existing query with an extra $and' do
557
+ it 'adds conditions to existing query' do
558
+ selection.selector.should == {
559
+ 'test' => 1,
560
+ mql_operator => ['hello' => 'world'],
561
+ }
562
+ end
563
+ end
564
+
565
+ context '$or' do
566
+ let(:mql_operator) { '$or' }
567
+
568
+ it_behaves_like 'adds conditions to existing query with an extra $and'
569
+ end
570
+
571
+ context '$nor' do
572
+ let(:mql_operator) { '$nor' }
573
+
574
+ it_behaves_like 'adds conditions to existing query with an extra $and'
575
+ end
576
+
577
+ context '$not' do
578
+ let(:mql_operator) { '$not' }
579
+
580
+ it_behaves_like 'adds conditions to existing query'
581
+ end
582
+
583
+ context '$and' do
584
+ let(:mql_operator) { '$and' }
585
+
586
+ it_behaves_like 'adds conditions to existing query'
587
+ end
588
+ end
589
+ end
590
+ end