mongoid 7.0.4 → 7.0.10
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/LICENSE +1 -0
- data/README.md +3 -2
- data/Rakefile +26 -0
- data/lib/mongoid.rb +2 -1
- data/lib/mongoid/association/embedded/embeds_many.rb +2 -1
- data/lib/mongoid/association/embedded/embeds_one.rb +2 -1
- data/lib/mongoid/association/proxy.rb +1 -1
- data/lib/mongoid/atomic.rb +13 -3
- data/lib/mongoid/atomic/paths/embedded.rb +1 -1
- data/lib/mongoid/attributes.rb +28 -20
- data/lib/mongoid/attributes/dynamic.rb +15 -14
- data/lib/mongoid/clients/sessions.rb +20 -4
- data/lib/mongoid/config/environment.rb +21 -8
- data/lib/mongoid/criteria.rb +7 -1
- data/lib/mongoid/criteria/modifiable.rb +13 -2
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
- data/lib/mongoid/criteria/queryable/extensions/time.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
- data/lib/mongoid/criteria/queryable/key.rb +67 -8
- data/lib/mongoid/criteria/queryable/mergeable.rb +5 -4
- data/lib/mongoid/criteria/queryable/selectable.rb +3 -4
- data/lib/mongoid/criteria/queryable/selector.rb +9 -31
- data/lib/mongoid/extensions/hash.rb +4 -2
- data/lib/mongoid/extensions/regexp.rb +1 -1
- data/lib/mongoid/extensions/string.rb +2 -2
- data/lib/mongoid/fields.rb +2 -1
- data/lib/mongoid/matchable.rb +14 -15
- data/lib/mongoid/matchable/all.rb +4 -3
- data/lib/mongoid/matchable/default.rb +71 -24
- data/lib/mongoid/matchable/regexp.rb +2 -2
- data/lib/mongoid/persistable/pushable.rb +11 -2
- data/lib/mongoid/persistence_context.rb +6 -6
- data/lib/mongoid/positional.rb +1 -1
- data/lib/mongoid/query_cache.rb +24 -11
- data/lib/mongoid/validatable/macros.rb +1 -1
- data/lib/mongoid/validatable/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +2 -1
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
- data/spec/README.md +18 -0
- data/spec/app/models/delegating_patient.rb +16 -0
- data/spec/integration/app_spec.rb +192 -0
- data/spec/integration/associations/embedded_spec.rb +62 -0
- data/spec/integration/criteria/date_field_spec.rb +41 -0
- data/spec/integration/criteria/time_with_zone_spec.rb +32 -0
- data/spec/integration/document_spec.rb +22 -0
- data/spec/integration/matchable_spec.rb +680 -0
- data/spec/lite_spec_helper.rb +15 -5
- data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
- data/spec/mongoid/association/embedded/embeds_many_spec.rb +10 -0
- data/spec/mongoid/association/embedded/embeds_one_spec.rb +0 -2
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +140 -1
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +105 -0
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +2 -1
- data/spec/mongoid/attributes/dynamic_spec.rb +153 -0
- data/spec/mongoid/attributes_spec.rb +19 -7
- data/spec/mongoid/clients/factory_spec.rb +2 -2
- data/spec/mongoid/clients/options_spec.rb +4 -4
- data/spec/mongoid/clients/sessions_spec.rb +20 -7
- data/spec/mongoid/clients/transactions_spec.rb +36 -15
- data/spec/mongoid/clients_spec.rb +2 -2
- data/spec/mongoid/contextual/atomic_spec.rb +20 -10
- data/spec/mongoid/contextual/geo_near_spec.rb +12 -2
- data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
- data/spec/mongoid/contextual/mongo_spec.rb +76 -53
- data/spec/mongoid/criteria/modifiable_spec.rb +59 -10
- data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +54 -0
- data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
- data/spec/mongoid/criteria/queryable/key_spec.rb +48 -6
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +762 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +5 -224
- data/spec/mongoid/criteria/queryable/selector_spec.rb +37 -0
- data/spec/mongoid/criteria_spec.rb +7 -2
- data/spec/mongoid/document_fields_spec.rb +88 -0
- data/spec/mongoid/document_persistence_context_spec.rb +33 -0
- data/spec/mongoid/indexable_spec.rb +6 -4
- data/spec/mongoid/matchable/default_spec.rb +10 -3
- data/spec/mongoid/matchable/regexp_spec.rb +2 -2
- data/spec/mongoid/matchable_spec.rb +2 -2
- data/spec/mongoid/persistable/pushable_spec.rb +55 -1
- data/spec/mongoid/query_cache_spec.rb +62 -8
- data/spec/mongoid/relations/proxy_spec.rb +1 -1
- data/spec/mongoid/scopable_spec.rb +2 -1
- data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
- data/spec/mongoid/tasks/database_spec.rb +1 -1
- data/spec/mongoid/validatable/uniqueness_spec.rb +33 -6
- data/spec/spec_helper.rb +4 -37
- data/spec/support/child_process_helper.rb +76 -0
- data/spec/support/cluster_config.rb +158 -0
- data/spec/support/constraints.rb +201 -30
- data/spec/support/expectations.rb +17 -3
- data/spec/support/spec_config.rb +12 -4
- metadata +490 -454
- metadata.gz.sig +0 -0
|
@@ -346,23 +346,35 @@ describe Time do
|
|
|
346
346
|
|
|
347
347
|
describe "#__evolve_date__" do
|
|
348
348
|
|
|
349
|
-
let(:time) do
|
|
350
|
-
Time.new(2010, 1, 1, 12, 0, 0)
|
|
351
|
-
end
|
|
352
|
-
|
|
353
349
|
let(:evolved) do
|
|
354
350
|
time.__evolve_date__
|
|
355
351
|
end
|
|
356
352
|
|
|
357
|
-
|
|
358
|
-
|
|
353
|
+
context 'beginning of day' do
|
|
354
|
+
let(:time) do
|
|
355
|
+
Time.new(2010, 1, 1, 0, 0, 1).freeze
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
it "returns midnight utc" do
|
|
359
|
+
expect(evolved).to eq(Time.utc(2010, 1, 1, 0, 0, 0))
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
context 'end of day' do
|
|
364
|
+
let(:time) do
|
|
365
|
+
Time.new(2010, 1, 1, 23, 59, 59).freeze
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it "returns midnight utc" do
|
|
369
|
+
expect(evolved).to eq(Time.utc(2010, 1, 1, 0, 0, 0))
|
|
370
|
+
end
|
|
359
371
|
end
|
|
360
372
|
end
|
|
361
373
|
|
|
362
374
|
describe "#__evolve_time__" do
|
|
363
375
|
|
|
364
376
|
let(:time) do
|
|
365
|
-
Time.new(2010, 1, 1, 12, 0, 0)
|
|
377
|
+
Time.new(2010, 1, 1, 12, 0, 0).freeze
|
|
366
378
|
end
|
|
367
379
|
|
|
368
380
|
let(:evolved) do
|
|
@@ -322,10 +322,37 @@ describe ActiveSupport::TimeWithZone do
|
|
|
322
322
|
end
|
|
323
323
|
end
|
|
324
324
|
|
|
325
|
+
describe "#__evolve_date__" do
|
|
326
|
+
|
|
327
|
+
let(:evolved) do
|
|
328
|
+
time.__evolve_date__
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
context 'beginning of day' do
|
|
332
|
+
let(:time) do
|
|
333
|
+
time_zone.local(2010, 1, 1, 0, 0, 1).freeze
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
it "returns midnight utc" do
|
|
337
|
+
expect(evolved).to eq(Time.utc(2010, 1, 1, 0, 0, 0))
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context 'end of day' do
|
|
342
|
+
let(:time) do
|
|
343
|
+
time_zone.local(2010, 1, 1, 23, 59, 59).freeze
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
it "returns midnight utc" do
|
|
347
|
+
expect(evolved).to eq(Time.utc(2010, 1, 1, 0, 0, 0))
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
325
352
|
describe "#__evolve_time__" do
|
|
326
353
|
|
|
327
354
|
let(:date) do
|
|
328
|
-
time_zone.local(2010, 1, 1, 12, 0, 0)
|
|
355
|
+
time_zone.local(2010, 1, 1, 12, 0, 0).freeze
|
|
329
356
|
end
|
|
330
357
|
|
|
331
358
|
let(:evolved) do
|
|
@@ -23,16 +23,58 @@ describe Mongoid::Criteria::Queryable::Key do
|
|
|
23
23
|
|
|
24
24
|
describe "#__expr_part__" do
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
context 'operator only' do
|
|
27
|
+
let(:key) do
|
|
28
|
+
described_class.new("field", :__union__, "$all")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
let(:specified) do
|
|
32
|
+
key.__expr_part__([ 1, 2 ])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "returns the name plus operator and value" do
|
|
36
|
+
expect(specified).to eq({ "field" => { "$all" => [ 1, 2 ] }})
|
|
37
|
+
end
|
|
28
38
|
end
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
key
|
|
40
|
+
context 'operator and expanded only' do
|
|
41
|
+
let(:key) do
|
|
42
|
+
described_class.new("field", :__override__, "$geoIntersects", '$geometry')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
let(:specified) do
|
|
46
|
+
key.__expr_part__([ 1, 10 ])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "returns the query expression" do
|
|
50
|
+
expect(specified).to eq({ "field" => {
|
|
51
|
+
'$geoIntersects' => {
|
|
52
|
+
'$geometry' => [1, 10],
|
|
53
|
+
},
|
|
54
|
+
}})
|
|
55
|
+
end
|
|
32
56
|
end
|
|
33
57
|
|
|
34
|
-
|
|
35
|
-
|
|
58
|
+
context 'operator, expanded and block' do
|
|
59
|
+
let(:key) do
|
|
60
|
+
described_class.new("field", :__override__, "$geoIntersects", '$geometry') do |value|
|
|
61
|
+
{ "type" => 'Point', "coordinates" => value }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
let(:specified) do
|
|
66
|
+
key.__expr_part__([ 1, 10 ])
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "returns the query expression" do
|
|
70
|
+
expect(specified).to eq({ "field" => {
|
|
71
|
+
'$geoIntersects' => {
|
|
72
|
+
'$geometry' => {
|
|
73
|
+
'type' => 'Point', 'coordinates' => [1, 10],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
}})
|
|
77
|
+
end
|
|
36
78
|
end
|
|
37
79
|
end
|
|
38
80
|
|
|
@@ -0,0 +1,762 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
require "spec_helper"
|
|
5
|
+
|
|
6
|
+
describe Mongoid::Criteria::Queryable::Selectable do
|
|
7
|
+
|
|
8
|
+
let(:query) do
|
|
9
|
+
Mongoid::Query.new("id" => "_id")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#and" do
|
|
13
|
+
|
|
14
|
+
context "when provided no criterion" do
|
|
15
|
+
|
|
16
|
+
let(:selection) do
|
|
17
|
+
query.and
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "does not add any criterion" do
|
|
21
|
+
expect(selection.selector).to eq({})
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "returns the query" do
|
|
25
|
+
expect(selection).to eq(query)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "returns a cloned query" do
|
|
29
|
+
expect(selection).to_not equal(query)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when provided nil" do
|
|
34
|
+
|
|
35
|
+
let(:selection) do
|
|
36
|
+
query.and(nil)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "does not add any criterion" do
|
|
40
|
+
expect(selection.selector).to eq({})
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "returns the query" do
|
|
44
|
+
expect(selection).to eq(query)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "returns a cloned query" do
|
|
48
|
+
expect(selection).to_not equal(query)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "when provided a single criterion" do
|
|
53
|
+
|
|
54
|
+
let(:selection) do
|
|
55
|
+
query.and(field: [ 1, 2 ])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "adds the $and selector" do
|
|
59
|
+
expect(selection.selector).to eq({
|
|
60
|
+
"$and" => [{ "field" => [ 1, 2 ] }]
|
|
61
|
+
})
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "returns a cloned query" do
|
|
65
|
+
expect(selection).to_not equal(query)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context "when provided a nested criterion" do
|
|
70
|
+
|
|
71
|
+
let(:selection) do
|
|
72
|
+
query.and(:test.elem_match => { :field.in => [ 1, 2 ] })
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "adds the $and selector" do
|
|
76
|
+
expect(selection.selector).to eq({
|
|
77
|
+
"$and" => [{ "test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}}]
|
|
78
|
+
})
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "returns a cloned query" do
|
|
82
|
+
expect(selection).to_not equal(query)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "when provided multiple criterion" do
|
|
87
|
+
|
|
88
|
+
context "when the criterion is already included" do
|
|
89
|
+
|
|
90
|
+
let(:selection) do
|
|
91
|
+
query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "does not duplicate the $and selector" do
|
|
95
|
+
expect(selection.selector).to eq({
|
|
96
|
+
"$and" => [
|
|
97
|
+
{ "first" => [ 1, 2 ] }
|
|
98
|
+
]
|
|
99
|
+
})
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "returns a cloned query" do
|
|
103
|
+
expect(selection).to_not equal(query)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "when the criterion are for different fields" do
|
|
108
|
+
|
|
109
|
+
let(:selection) do
|
|
110
|
+
query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "adds the $and selector" do
|
|
114
|
+
expect(selection.selector).to eq({
|
|
115
|
+
"$and" => [
|
|
116
|
+
{ "first" => [ 1, 2 ] },
|
|
117
|
+
{ "second" => [ 3, 4 ] }
|
|
118
|
+
]
|
|
119
|
+
})
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "returns a cloned query" do
|
|
123
|
+
expect(selection).to_not equal(query)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "when the criterion are on the same field" do
|
|
128
|
+
|
|
129
|
+
let(:selection) do
|
|
130
|
+
query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "appends both $and expressions" do
|
|
134
|
+
expect(selection.selector).to eq({
|
|
135
|
+
"$and" => [
|
|
136
|
+
{ "first" => [ 1, 2 ] },
|
|
137
|
+
{ "first" => [ 3, 4 ] }
|
|
138
|
+
]
|
|
139
|
+
})
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "returns a cloned query" do
|
|
143
|
+
expect(selection).to_not equal(query)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context "when chaining the criterion" do
|
|
149
|
+
|
|
150
|
+
context "when the criterion are for different fields" do
|
|
151
|
+
|
|
152
|
+
let(:selection) do
|
|
153
|
+
query.and(first: [ 1, 2 ]).and(second: [ 3, 4 ])
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "adds the $and selectors" do
|
|
157
|
+
expect(selection.selector).to eq({
|
|
158
|
+
"$and" => [
|
|
159
|
+
{ "first" => [ 1, 2 ] },
|
|
160
|
+
{ "second" => [ 3, 4 ] }
|
|
161
|
+
]
|
|
162
|
+
})
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "returns a cloned query" do
|
|
166
|
+
expect(selection).to_not equal(query)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "when the criterion are on the same field" do
|
|
171
|
+
|
|
172
|
+
let(:selection) do
|
|
173
|
+
query.and(first: [ 1, 2 ]).and(first: [ 3, 4 ])
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "appends both $and expressions" do
|
|
177
|
+
expect(selection.selector).to eq({
|
|
178
|
+
"$and" => [
|
|
179
|
+
{ "first" => [ 1, 2 ] },
|
|
180
|
+
{ "first" => [ 3, 4 ] }
|
|
181
|
+
]
|
|
182
|
+
})
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it "returns a cloned query" do
|
|
186
|
+
expect(selection).to_not equal(query)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
describe "#or" do
|
|
193
|
+
|
|
194
|
+
context "when provided no criterion" do
|
|
195
|
+
|
|
196
|
+
let(:selection) do
|
|
197
|
+
query.or
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "does not add any criterion" do
|
|
201
|
+
expect(selection.selector).to eq({})
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "returns the query" do
|
|
205
|
+
expect(selection).to eq(query)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "returns a cloned query" do
|
|
209
|
+
expect(selection).to_not equal(query)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
context "when provided nil" do
|
|
214
|
+
|
|
215
|
+
let(:selection) do
|
|
216
|
+
query.or(nil)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "does not add any criterion" do
|
|
220
|
+
expect(selection.selector).to eq({})
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "returns the query" do
|
|
224
|
+
expect(selection).to eq(query)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "returns a cloned query" do
|
|
228
|
+
expect(selection).to_not equal(query)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context "when provided a single criterion" do
|
|
233
|
+
|
|
234
|
+
let(:selection) do
|
|
235
|
+
query.or(field: [ 1, 2 ])
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "adds the $or selector" do
|
|
239
|
+
expect(selection.selector).to eq({
|
|
240
|
+
"$or" => [{ "field" => [ 1, 2 ] }]
|
|
241
|
+
})
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "returns a cloned query" do
|
|
245
|
+
expect(selection).to_not equal(query)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
context "when provided multiple criterion" do
|
|
250
|
+
|
|
251
|
+
context "when the criterion are for different fields" do
|
|
252
|
+
|
|
253
|
+
let(:selection) do
|
|
254
|
+
query.or({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it "adds the $or selector" do
|
|
258
|
+
expect(selection.selector).to eq({
|
|
259
|
+
"$or" => [
|
|
260
|
+
{ "first" => [ 1, 2 ] },
|
|
261
|
+
{ "second" => [ 3, 4 ] }
|
|
262
|
+
]
|
|
263
|
+
})
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "returns a cloned query" do
|
|
267
|
+
expect(selection).to_not equal(query)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
context "when a criterion has a selectable key" do
|
|
272
|
+
|
|
273
|
+
let(:selection) do
|
|
274
|
+
query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "adds the $or selector" do
|
|
278
|
+
expect(selection.selector).to eq({
|
|
279
|
+
"$or" => [
|
|
280
|
+
{ "first" => [ 1, 2 ] },
|
|
281
|
+
{ "second" => { "$gt" => 3 }}
|
|
282
|
+
]
|
|
283
|
+
})
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "returns a cloned query" do
|
|
287
|
+
expect(selection).to_not equal(query)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
context "when the criterion has an aliased field" do
|
|
292
|
+
|
|
293
|
+
let(:selection) do
|
|
294
|
+
query.or({ id: 1 })
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it "adds the $or selector and aliases the field" do
|
|
298
|
+
expect(selection.selector).to eq({
|
|
299
|
+
"$or" => [ { "_id" => 1 } ]
|
|
300
|
+
})
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it "returns a cloned query" do
|
|
304
|
+
expect(selection).to_not equal(query)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
context "when a criterion is wrapped in an array" do
|
|
309
|
+
|
|
310
|
+
let(:selection) do
|
|
311
|
+
query.or([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it "adds the $or selector" do
|
|
315
|
+
expect(selection.selector).to eq({
|
|
316
|
+
"$or" => [
|
|
317
|
+
{ "first" => [ 1, 2 ] },
|
|
318
|
+
{ "second" => { "$gt" => 3 }}
|
|
319
|
+
]
|
|
320
|
+
})
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
it "returns a cloned query" do
|
|
324
|
+
expect(selection).to_not equal(query)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
context "when the criterion are on the same field" do
|
|
329
|
+
|
|
330
|
+
let(:selection) do
|
|
331
|
+
query.or({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it "appends both $or expressions" do
|
|
335
|
+
expect(selection.selector).to eq({
|
|
336
|
+
"$or" => [
|
|
337
|
+
{ "first" => [ 1, 2 ] },
|
|
338
|
+
{ "first" => [ 3, 4 ] }
|
|
339
|
+
]
|
|
340
|
+
})
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it "returns a cloned query" do
|
|
344
|
+
expect(selection).to_not equal(query)
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context "when chaining the criterion" do
|
|
350
|
+
|
|
351
|
+
context "when the criterion are for different fields" do
|
|
352
|
+
|
|
353
|
+
let(:selection) do
|
|
354
|
+
query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
it "adds the $or selectors" do
|
|
358
|
+
expect(selection.selector).to eq({
|
|
359
|
+
"$or" => [
|
|
360
|
+
{ "first" => [ 1, 2 ] },
|
|
361
|
+
{ "second" => [ 3, 4 ] }
|
|
362
|
+
]
|
|
363
|
+
})
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
it "returns a cloned query" do
|
|
367
|
+
expect(selection).to_not equal(query)
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
context "when the criterion are on the same field" do
|
|
372
|
+
|
|
373
|
+
let(:selection) do
|
|
374
|
+
query.or(first: [ 1, 2 ]).or(first: [ 3, 4 ])
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it "appends both $or expressions" do
|
|
378
|
+
expect(selection.selector).to eq({
|
|
379
|
+
"$or" => [
|
|
380
|
+
{ "first" => [ 1, 2 ] },
|
|
381
|
+
{ "first" => [ 3, 4 ] }
|
|
382
|
+
]
|
|
383
|
+
})
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
it "returns a cloned query" do
|
|
387
|
+
expect(selection).to_not equal(query)
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
describe "#nor" do
|
|
394
|
+
|
|
395
|
+
context "when provided no criterion" do
|
|
396
|
+
|
|
397
|
+
let(:selection) do
|
|
398
|
+
query.nor
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
it "does not add any criterion" do
|
|
402
|
+
expect(selection.selector).to eq({})
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it "returns the query" do
|
|
406
|
+
expect(selection).to eq(query)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
it "returns a cloned query" do
|
|
410
|
+
expect(selection).to_not equal(query)
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
context "when provided nil" do
|
|
415
|
+
|
|
416
|
+
let(:selection) do
|
|
417
|
+
query.nor(nil)
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
it "does not add any criterion" do
|
|
421
|
+
expect(selection.selector).to eq({})
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it "returns the query" do
|
|
425
|
+
expect(selection).to eq(query)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it "returns a cloned query" do
|
|
429
|
+
expect(selection).to_not equal(query)
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
context "when provided a single criterion" do
|
|
434
|
+
|
|
435
|
+
let(:selection) do
|
|
436
|
+
query.nor(field: [ 1, 2 ])
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
it "adds the $nor selector" do
|
|
440
|
+
expect(selection.selector).to eq({
|
|
441
|
+
"$nor" => [{"field" => [ 1, 2 ] }]
|
|
442
|
+
})
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
it "returns a cloned query" do
|
|
446
|
+
expect(selection).to_not equal(query)
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
context "when provided multiple criterion" do
|
|
451
|
+
|
|
452
|
+
context "when the criterion are fnor different fields" do
|
|
453
|
+
|
|
454
|
+
let(:selection) do
|
|
455
|
+
query.nor({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
it "adds the $nor selector" do
|
|
459
|
+
expect(selection.selector).to eq({
|
|
460
|
+
"$nor" => [
|
|
461
|
+
{ "first" => [ 1, 2 ] },
|
|
462
|
+
{ "second" => [ 3, 4 ] }
|
|
463
|
+
]
|
|
464
|
+
})
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
it "returns a cloned query" do
|
|
468
|
+
expect(selection).to_not equal(query)
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
context "when the criterion are on the same field" do
|
|
473
|
+
|
|
474
|
+
let(:selection) do
|
|
475
|
+
query.nor({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it "appends both $nor expressions" do
|
|
479
|
+
expect(selection.selector).to eq({
|
|
480
|
+
"$nor" => [
|
|
481
|
+
{ "first" => [ 1, 2 ] },
|
|
482
|
+
{ "first" => [ 3, 4 ] }
|
|
483
|
+
]
|
|
484
|
+
})
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it "returns a cloned query" do
|
|
488
|
+
expect(selection).to_not equal(query)
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
context "when chaining the criterion" do
|
|
494
|
+
|
|
495
|
+
context "when the criterion are fnor different fields" do
|
|
496
|
+
|
|
497
|
+
let(:selection) do
|
|
498
|
+
query.nor(first: [ 1, 2 ]).nor(second: [ 3, 4 ])
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
it "adds the $nor selectors" do
|
|
502
|
+
expect(selection.selector).to eq({
|
|
503
|
+
"$nor" => [
|
|
504
|
+
{ "first" => [ 1, 2 ] },
|
|
505
|
+
{ "second" => [ 3, 4 ] }
|
|
506
|
+
]
|
|
507
|
+
})
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
it "returns a cloned query" do
|
|
511
|
+
expect(selection).to_not equal(query)
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
context "when the criterion are on the same field" do
|
|
516
|
+
|
|
517
|
+
let(:selection) do
|
|
518
|
+
query.nor(first: [ 1, 2 ]).nor(first: [ 3, 4 ])
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
it "appends both $nor expressions" do
|
|
522
|
+
expect(selection.selector).to eq({
|
|
523
|
+
"$nor" => [
|
|
524
|
+
{ "first" => [ 1, 2 ] },
|
|
525
|
+
{ "first" => [ 3, 4 ] }
|
|
526
|
+
]
|
|
527
|
+
})
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
it "returns a cloned query" do
|
|
531
|
+
expect(selection).to_not equal(query)
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
describe "#not" do
|
|
538
|
+
|
|
539
|
+
context "when provided no criterion" do
|
|
540
|
+
|
|
541
|
+
let(:selection) do
|
|
542
|
+
query.not
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
it "does not add any criterion" do
|
|
546
|
+
expect(selection.selector).to eq({})
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
it "returns the query" do
|
|
550
|
+
expect(selection).to eq(query)
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
it "returns a cloned query" do
|
|
554
|
+
expect(selection).not_to equal(query)
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
it 'does not mutate receiver' do
|
|
558
|
+
expect(query.negating).to be nil
|
|
559
|
+
|
|
560
|
+
selection
|
|
561
|
+
expect(query.negating).to be nil
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
context "when the following criteria is a query method" do
|
|
565
|
+
|
|
566
|
+
let(:selection) do
|
|
567
|
+
query.not.all(field: [ 1, 2 ])
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
it "negates the all selection" do
|
|
571
|
+
expect(selection.selector).to eq(
|
|
572
|
+
{ "field" => { "$not" => { "$all" => [ 1, 2 ] }}}
|
|
573
|
+
)
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
it "returns a cloned query" do
|
|
577
|
+
expect(selection).to_not equal(query)
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
it "removes the negation on the clone" do
|
|
581
|
+
expect(selection).to_not be_negating
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
context "when the following criteria is a gt method" do
|
|
586
|
+
|
|
587
|
+
let(:selection) do
|
|
588
|
+
query.not.gt(age: 50)
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
it "negates the gt selection" do
|
|
592
|
+
expect(selection.selector).to eq(
|
|
593
|
+
{ "age" => { "$not" => { "$gt" => 50 }}}
|
|
594
|
+
)
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
it "returns a coned query" do
|
|
598
|
+
expect(selection).to_not eq(query)
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
it "removes the negation on the clone" do
|
|
602
|
+
expect(selection).to_not be_negating
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
context "when the following criteria is a where" do
|
|
607
|
+
|
|
608
|
+
let(:selection) do
|
|
609
|
+
query.not.where(field: 1, :other.in => [ 1, 2 ])
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
it "negates the selection with an operator" do
|
|
613
|
+
expect(selection.selector).to eq(
|
|
614
|
+
{ "field" => { "$ne" => 1 }, "other" => { "$not" => { "$in" => [ 1, 2 ] }}}
|
|
615
|
+
)
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
it "returns a cloned query" do
|
|
619
|
+
expect(selection).to_not equal(query)
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
it "removes the negation on the clone" do
|
|
623
|
+
expect(selection).to_not be_negating
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
context "when the following criteria is a where with a regexp" do
|
|
628
|
+
|
|
629
|
+
let(:selection) do
|
|
630
|
+
query.not.where(field: 1, other: /test/)
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
it "negates the selection with an operator" do
|
|
634
|
+
expect(selection.selector).to eq(
|
|
635
|
+
{ "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
|
|
636
|
+
)
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
it "returns a cloned query" do
|
|
640
|
+
expect(selection).to_not equal(query)
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
it "removes the negation on the clone" do
|
|
644
|
+
expect(selection).to_not be_negating
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
context "when provided nil" do
|
|
651
|
+
|
|
652
|
+
let(:selection) do
|
|
653
|
+
query.not(nil)
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
it "does not add any criterion" do
|
|
657
|
+
expect(selection.selector).to eq({})
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
it "returns the query" do
|
|
661
|
+
expect(selection).to eq(query)
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
it "returns a cloned query" do
|
|
665
|
+
expect(selection).to_not equal(query)
|
|
666
|
+
end
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
context "when provided a single criterion" do
|
|
670
|
+
|
|
671
|
+
let(:selection) do
|
|
672
|
+
query.not(field: /test/)
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
it "adds the $not selector" do
|
|
676
|
+
expect(selection.selector).to eq({
|
|
677
|
+
"field" => { "$not" => /test/ }
|
|
678
|
+
})
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
it "returns a cloned query" do
|
|
682
|
+
expect(selection).to_not equal(query)
|
|
683
|
+
end
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
context "when provided multiple criterion" do
|
|
687
|
+
|
|
688
|
+
context "when the criterion are for different fields" do
|
|
689
|
+
|
|
690
|
+
let(:selection) do
|
|
691
|
+
query.not(first: /1/, second: /2/)
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
it "adds the $not selectors" do
|
|
695
|
+
expect(selection.selector).to eq({
|
|
696
|
+
"first" => { "$not" => /1/ },
|
|
697
|
+
"second" => { "$not" => /2/ }
|
|
698
|
+
})
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
it "returns a cloned query" do
|
|
702
|
+
expect(selection).to_not equal(query)
|
|
703
|
+
end
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
context "when chaining the criterion" do
|
|
708
|
+
|
|
709
|
+
context "when the criterion are for different fields" do
|
|
710
|
+
|
|
711
|
+
let(:selection) do
|
|
712
|
+
query.not(first: /1/).not(second: /2/)
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
it "adds the $not selectors" do
|
|
716
|
+
expect(selection.selector).to eq({
|
|
717
|
+
"first" => { "$not" => /1/ },
|
|
718
|
+
"second" => { "$not" => /2/ }
|
|
719
|
+
})
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
it "returns a cloned query" do
|
|
723
|
+
expect(selection).to_not equal(query)
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
context "when the criterion are on the same field" do
|
|
728
|
+
|
|
729
|
+
let(:selection) do
|
|
730
|
+
query.not(first: /1/).not(first: /2/)
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
it "overwrites the first $not selector" do
|
|
734
|
+
expect(selection.selector).to eq({
|
|
735
|
+
"first" => { "$not" => /2/ }
|
|
736
|
+
})
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
it "returns a cloned query" do
|
|
740
|
+
expect(selection).to_not equal(query)
|
|
741
|
+
end
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
context "when the criterion are a double negative" do
|
|
745
|
+
|
|
746
|
+
let(:selection) do
|
|
747
|
+
query.not.where(:first.not => /1/)
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
it "does not double the $not selector" do
|
|
751
|
+
expect(selection.selector).to eq({
|
|
752
|
+
"first" => { "$not" => /1/ }
|
|
753
|
+
})
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
it "returns a cloned query" do
|
|
757
|
+
expect(selection).to_not equal(query)
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
end
|
|
761
|
+
end
|
|
762
|
+
end
|