mongoid 5.4.1 → 6.1.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 +5 -5
- data/README.md +3 -3
- data/lib/config/locales/en.yml +19 -0
- data/lib/mongoid.rb +4 -4
- data/lib/mongoid/atomic.rb +2 -2
- data/lib/mongoid/atomic/modifiers.rb +8 -12
- data/lib/mongoid/attributes.rb +22 -21
- data/lib/mongoid/attributes/readonly.rb +22 -0
- data/lib/mongoid/cacheable.rb +36 -0
- data/lib/mongoid/changeable.rb +36 -0
- data/lib/mongoid/clients.rb +8 -63
- data/lib/mongoid/clients/options.rb +55 -250
- data/lib/mongoid/clients/storage_options.rb +1 -69
- data/lib/mongoid/composable.rb +29 -3
- data/lib/mongoid/config.rb +1 -0
- data/lib/mongoid/contextual/atomic.rb +5 -8
- data/lib/mongoid/contextual/map_reduce.rb +0 -4
- data/lib/mongoid/contextual/memory.rb +2 -2
- data/lib/mongoid/contextual/mongo.rb +40 -22
- data/lib/mongoid/contextual/none.rb +12 -0
- data/lib/mongoid/copyable.rb +13 -6
- data/lib/mongoid/criteria.rb +5 -2
- data/lib/mongoid/criteria/marshalable.rb +2 -2
- data/lib/mongoid/criteria/modifiable.rb +17 -1
- data/lib/mongoid/criteria/options.rb +25 -0
- data/lib/mongoid/criteria/queryable.rb +87 -0
- data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
- data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
- data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
- data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
- data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
- data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
- data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
- data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
- data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
- data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
- data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
- data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
- data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
- data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
- data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
- data/lib/mongoid/criteria/queryable/key.rb +103 -0
- data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
- data/lib/mongoid/criteria/queryable/mergeable.rb +271 -0
- data/lib/mongoid/criteria/queryable/optional.rb +429 -0
- data/lib/mongoid/criteria/queryable/options.rb +153 -0
- data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
- data/lib/mongoid/criteria/queryable/selectable.rb +662 -0
- data/lib/mongoid/criteria/queryable/selector.rb +212 -0
- data/lib/mongoid/criteria/queryable/smash.rb +104 -0
- data/lib/mongoid/document.rb +30 -37
- data/lib/mongoid/errors.rb +2 -0
- data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
- data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
- data/lib/mongoid/errors/invalid_field.rb +2 -2
- data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
- data/lib/mongoid/errors/invalid_relation.rb +66 -0
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions.rb +0 -4
- data/lib/mongoid/extensions/big_decimal.rb +17 -8
- data/lib/mongoid/extensions/date.rb +4 -1
- data/lib/mongoid/extensions/decimal128.rb +3 -3
- data/lib/mongoid/extensions/hash.rb +1 -0
- data/lib/mongoid/extensions/string.rb +4 -3
- data/lib/mongoid/extensions/time.rb +4 -1
- data/lib/mongoid/fields/validators/macro.rb +18 -0
- data/lib/mongoid/findable.rb +2 -2
- data/lib/mongoid/indexable.rb +15 -13
- data/lib/mongoid/interceptable.rb +5 -22
- data/lib/mongoid/matchable.rb +13 -7
- data/lib/mongoid/matchable/all.rb +2 -2
- data/lib/mongoid/matchable/and.rb +3 -3
- data/lib/mongoid/matchable/default.rb +2 -2
- data/lib/mongoid/matchable/elem_match.rb +28 -0
- data/lib/mongoid/matchable/exists.rb +2 -2
- data/lib/mongoid/matchable/gt.rb +4 -2
- data/lib/mongoid/matchable/gte.rb +4 -2
- data/lib/mongoid/matchable/in.rb +2 -2
- data/lib/mongoid/matchable/lt.rb +4 -2
- data/lib/mongoid/matchable/lte.rb +4 -2
- data/lib/mongoid/matchable/ne.rb +2 -2
- data/lib/mongoid/matchable/nin.rb +2 -2
- data/lib/mongoid/matchable/or.rb +3 -3
- data/lib/mongoid/matchable/regexp.rb +3 -3
- data/lib/mongoid/matchable/size.rb +2 -2
- data/lib/mongoid/persistable.rb +3 -5
- data/lib/mongoid/persistable/creatable.rb +2 -2
- data/lib/mongoid/persistable/deletable.rb +1 -1
- data/lib/mongoid/persistable/settable.rb +1 -1
- data/lib/mongoid/persistable/updatable.rb +5 -12
- data/lib/mongoid/persistable/upsertable.rb +1 -1
- data/lib/mongoid/persistence_context.rb +215 -0
- data/lib/mongoid/query_cache.rb +3 -6
- data/lib/mongoid/relations/accessors.rb +3 -0
- data/lib/mongoid/relations/auto_save.rb +12 -4
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
- data/lib/mongoid/relations/counter_cache.rb +15 -5
- data/lib/mongoid/relations/eager.rb +6 -11
- data/lib/mongoid/relations/eager/base.rb +3 -3
- data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
- data/lib/mongoid/relations/eager/has_many.rb +1 -1
- data/lib/mongoid/relations/embedded/batchable.rb +12 -36
- data/lib/mongoid/relations/embedded/in.rb +13 -1
- data/lib/mongoid/relations/embedded/many.rb +28 -10
- data/lib/mongoid/relations/embedded/one.rb +14 -1
- data/lib/mongoid/relations/macros.rb +9 -1
- data/lib/mongoid/relations/metadata.rb +3 -3
- data/lib/mongoid/relations/options.rb +2 -2
- data/lib/mongoid/relations/proxy.rb +1 -31
- data/lib/mongoid/relations/referenced/in.rb +19 -10
- data/lib/mongoid/relations/referenced/many.rb +23 -17
- data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
- data/lib/mongoid/relations/referenced/one.rb +15 -1
- data/lib/mongoid/relations/synchronization.rb +11 -11
- data/lib/mongoid/relations/touchable.rb +6 -3
- data/lib/mongoid/reloadable.rb +1 -1
- data/lib/mongoid/serializable.rb +1 -1
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/validatable/uniqueness.rb +1 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +14 -3
- data/spec/app/models/album.rb +5 -1
- data/spec/app/models/artist.rb +21 -0
- data/spec/app/models/book.rb +2 -1
- data/spec/app/models/dokument.rb +1 -0
- data/spec/app/models/ordered_post.rb +5 -0
- data/spec/app/models/oscar.rb +1 -2
- data/spec/app/models/page.rb +1 -1
- data/spec/app/models/person.rb +3 -3
- data/spec/app/models/princess.rb +2 -0
- data/spec/app/models/record.rb +1 -0
- data/spec/app/models/subscription.rb +1 -0
- data/spec/app/models/thing.rb +1 -1
- data/spec/config/mongoid.yml +15 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
- data/spec/mongoid/atomic_spec.rb +17 -17
- data/spec/mongoid/attributes/nested_spec.rb +14 -14
- data/spec/mongoid/attributes/readonly_spec.rb +87 -44
- data/spec/mongoid/attributes_spec.rb +90 -5
- data/spec/mongoid/cacheable_spec.rb +112 -0
- data/spec/mongoid/changeable_spec.rb +58 -0
- data/spec/mongoid/clients/factory_spec.rb +31 -3
- data/spec/mongoid/clients/options_spec.rb +382 -96
- data/spec/mongoid/clients_spec.rb +243 -101
- data/spec/mongoid/composable_spec.rb +7 -0
- data/spec/mongoid/config_spec.rb +67 -11
- data/spec/mongoid/contextual/atomic_spec.rb +3 -3
- data/spec/mongoid/contextual/mongo_spec.rb +165 -20
- data/spec/mongoid/contextual/none_spec.rb +15 -0
- data/spec/mongoid/copyable_spec.rb +13 -4
- data/spec/mongoid/criteria/modifiable_spec.rb +239 -7
- data/spec/mongoid/criteria/options_spec.rb +29 -0
- data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
- data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
- data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
- data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
- data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
- data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
- data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
- data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
- data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
- data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
- data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
- data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
- data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
- data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
- data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
- data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
- data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
- data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
- data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
- data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
- data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +4174 -0
- data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
- data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
- data/spec/mongoid/criteria_spec.rb +152 -21
- data/spec/mongoid/document_spec.rb +37 -88
- data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
- data/spec/mongoid/extensions/big_decimal_spec.rb +320 -18
- data/spec/mongoid/extensions/boolean_spec.rb +14 -0
- data/spec/mongoid/extensions/date_spec.rb +2 -6
- data/spec/mongoid/extensions/date_time_spec.rb +2 -6
- data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
- data/spec/mongoid/extensions/float_spec.rb +8 -1
- data/spec/mongoid/extensions/hash_spec.rb +15 -0
- data/spec/mongoid/extensions/integer_spec.rb +8 -1
- data/spec/mongoid/extensions/object_spec.rb +11 -0
- data/spec/mongoid/extensions/string_spec.rb +21 -0
- data/spec/mongoid/extensions/time_spec.rb +2 -6
- data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
- data/spec/mongoid/findable_spec.rb +46 -1
- data/spec/mongoid/indexable_spec.rb +15 -3
- data/spec/mongoid/interceptable_spec.rb +68 -10
- data/spec/mongoid/matchable/all_spec.rb +4 -4
- data/spec/mongoid/matchable/and_spec.rb +10 -10
- data/spec/mongoid/matchable/default_spec.rb +12 -12
- data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
- data/spec/mongoid/matchable/exists_spec.rb +5 -5
- data/spec/mongoid/matchable/gt_spec.rb +18 -7
- data/spec/mongoid/matchable/gte_spec.rb +17 -7
- data/spec/mongoid/matchable/in_spec.rb +5 -5
- data/spec/mongoid/matchable/lt_spec.rb +18 -7
- data/spec/mongoid/matchable/lte_spec.rb +18 -7
- data/spec/mongoid/matchable/ne_spec.rb +5 -5
- data/spec/mongoid/matchable/nin_spec.rb +5 -5
- data/spec/mongoid/matchable/or_spec.rb +7 -7
- data/spec/mongoid/matchable/regexp_spec.rb +5 -5
- data/spec/mongoid/matchable/size_spec.rb +3 -3
- data/spec/mongoid/matchable_spec.rb +173 -53
- data/spec/mongoid/persistable/creatable_spec.rb +7 -2
- data/spec/mongoid/persistable/deletable_spec.rb +16 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +6 -2
- data/spec/mongoid/persistable/savable_spec.rb +35 -30
- data/spec/mongoid/persistable/settable_spec.rb +45 -29
- data/spec/mongoid/persistable/updatable_spec.rb +184 -5
- data/spec/mongoid/persistence_context_spec.rb +680 -0
- data/spec/mongoid/positional_spec.rb +10 -10
- data/spec/mongoid/query_cache_spec.rb +89 -0
- data/spec/mongoid/relations/accessors_spec.rb +1 -1
- data/spec/mongoid/relations/auto_save_spec.rb +39 -6
- data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
- data/spec/mongoid/relations/builders_spec.rb +37 -10
- data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
- data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
- data/spec/mongoid/relations/eager_spec.rb +40 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +63 -47
- data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
- data/spec/mongoid/relations/macros_spec.rb +395 -7
- data/spec/mongoid/relations/metadata_spec.rb +15 -1
- data/spec/mongoid/relations/proxy_spec.rb +27 -1
- data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
- data/spec/mongoid/relations/referenced/many_spec.rb +13 -25
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
- data/spec/mongoid/relations/synchronization_spec.rb +48 -2
- data/spec/mongoid/relations/touchable_spec.rb +40 -0
- data/spec/mongoid/reloadable_spec.rb +51 -0
- data/spec/mongoid/serializable_spec.rb +0 -50
- data/spec/mongoid/validatable/presence_spec.rb +1 -1
- data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
- data/spec/mongoid/validatable_spec.rb +16 -0
- data/spec/spec_helper.rb +20 -11
- metadata +524 -469
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongoid/clients/thread_options.rb +0 -19
- data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
- metadata.gz.sig +0 -0
@@ -0,0 +1,844 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Criteria::Queryable::Selector do
|
4
|
+
|
5
|
+
describe "merge!" do
|
6
|
+
|
7
|
+
let(:selector) do
|
8
|
+
described_class.new
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when selector is nested" do
|
12
|
+
|
13
|
+
before do
|
14
|
+
selector[:field] = selection
|
15
|
+
selector.merge!(other)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:selection) do
|
19
|
+
{ "$lt" => 50 }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when other contains same key with a hash" do
|
23
|
+
|
24
|
+
let(:other) do
|
25
|
+
{ "field" => { "$gt" => 20 } }
|
26
|
+
end
|
27
|
+
|
28
|
+
it "deep merges" do
|
29
|
+
expect(selector['field']).to eq({"$lt"=>50, "$gt" => 20})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when other contains same key without hash" do
|
34
|
+
|
35
|
+
let(:other) do
|
36
|
+
{ "field" => 10 }
|
37
|
+
end
|
38
|
+
|
39
|
+
it "merges" do
|
40
|
+
expect(selector['field']).to eq(10)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when selector contains a $nin" do
|
46
|
+
|
47
|
+
let(:initial) do
|
48
|
+
{ "$nin" => ["foo"] }
|
49
|
+
end
|
50
|
+
|
51
|
+
before do
|
52
|
+
selector["field"] = initial
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when merging in a new $nin" do
|
56
|
+
|
57
|
+
let(:other) do
|
58
|
+
{ "field" => { "$nin" => ["bar"] } }
|
59
|
+
end
|
60
|
+
|
61
|
+
before do
|
62
|
+
selector.merge!(other)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "combines the two $nin queries into one" do
|
66
|
+
expect(selector).to eq({
|
67
|
+
"field" => { "$nin" => ["foo", "bar"] }
|
68
|
+
})
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when selector contains a $in" do
|
74
|
+
|
75
|
+
let(:initial) do
|
76
|
+
{ "$in" => [1, 2] }
|
77
|
+
end
|
78
|
+
|
79
|
+
before do
|
80
|
+
selector["field"] = initial
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when merging in a new $in with an intersecting value" do
|
84
|
+
|
85
|
+
let(:other) do
|
86
|
+
{ "field" => { "$in" => [1] } }
|
87
|
+
end
|
88
|
+
|
89
|
+
before do
|
90
|
+
selector.merge!(other)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "intersects the $in values" do
|
94
|
+
expect(selector).to eq({
|
95
|
+
"field" => { "$in" => [1] }
|
96
|
+
})
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when merging in a new $in with no intersecting values" do
|
101
|
+
|
102
|
+
let(:other) do
|
103
|
+
{ "field" => { "$in" => [3] } }
|
104
|
+
end
|
105
|
+
|
106
|
+
before do
|
107
|
+
selector.merge!(other)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "intersects the $in values" do
|
111
|
+
expect(selector).to eq({
|
112
|
+
"field" => { "$in" => [] }
|
113
|
+
})
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context "when selector is not nested" do
|
119
|
+
|
120
|
+
before do
|
121
|
+
selector[:field] = selection
|
122
|
+
selector.merge!(other)
|
123
|
+
end
|
124
|
+
|
125
|
+
let(:selection) do
|
126
|
+
50
|
127
|
+
end
|
128
|
+
|
129
|
+
let(:other) do
|
130
|
+
{ "field" => { "$gt" => 20 } }
|
131
|
+
end
|
132
|
+
|
133
|
+
it "merges" do
|
134
|
+
expect(selector['field']).to eq({ "$gt" => 20 })
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when an object does not support the | operator' do
|
139
|
+
|
140
|
+
before do
|
141
|
+
selector['start'] = selection
|
142
|
+
selector.merge!(other)
|
143
|
+
end
|
144
|
+
|
145
|
+
let(:selection) do
|
146
|
+
{ '$lt' => Time.now }
|
147
|
+
end
|
148
|
+
|
149
|
+
let(:other) do
|
150
|
+
{ 'start' => selection, 'name' => 'test', }
|
151
|
+
end
|
152
|
+
|
153
|
+
it "merges" do
|
154
|
+
expect(selector['name']).to eq('test')
|
155
|
+
expect(selector['start']).to eq(selection)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "when the selector contains an $or" do
|
160
|
+
|
161
|
+
let(:initial) do
|
162
|
+
[{ "value" => 1 }]
|
163
|
+
end
|
164
|
+
|
165
|
+
before do
|
166
|
+
selector["$or"] = initial
|
167
|
+
end
|
168
|
+
|
169
|
+
context "when merging in a new $or" do
|
170
|
+
|
171
|
+
let(:other) do
|
172
|
+
[{ "value" => 2 }]
|
173
|
+
end
|
174
|
+
|
175
|
+
before do
|
176
|
+
selector.merge!({ "$or" => other })
|
177
|
+
end
|
178
|
+
|
179
|
+
it "combines the two $or queries into one" do
|
180
|
+
expect(selector).to eq({
|
181
|
+
"$or" => [{ "value" => 1 }, { "value" => 2 }]
|
182
|
+
})
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "when the selector contains an $and" do
|
188
|
+
|
189
|
+
let(:initial) do
|
190
|
+
[{ "value" => 1 }]
|
191
|
+
end
|
192
|
+
|
193
|
+
before do
|
194
|
+
selector["$and"] = initial
|
195
|
+
end
|
196
|
+
|
197
|
+
context "when merging in a new $and" do
|
198
|
+
|
199
|
+
let(:other) do
|
200
|
+
[{ "value" => 2 }]
|
201
|
+
end
|
202
|
+
|
203
|
+
before do
|
204
|
+
selector.merge!({ "$and" => other })
|
205
|
+
end
|
206
|
+
|
207
|
+
it "combines the two $and queries into one" do
|
208
|
+
expect(selector).to eq({
|
209
|
+
"$and" => [{ "value" => 1 }, { "value" => 2 }]
|
210
|
+
})
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context "when the selector contains a $nor" do
|
216
|
+
|
217
|
+
let(:initial) do
|
218
|
+
[{ "value" => 1 }]
|
219
|
+
end
|
220
|
+
|
221
|
+
before do
|
222
|
+
selector["$nor"] = initial
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when merging in a new $nor" do
|
226
|
+
|
227
|
+
let(:other) do
|
228
|
+
[{ "value" => 2 }]
|
229
|
+
end
|
230
|
+
|
231
|
+
before do
|
232
|
+
selector.merge!({ "$nor" => other })
|
233
|
+
end
|
234
|
+
|
235
|
+
it "combines the two $nor queries into one" do
|
236
|
+
expect(selector).to eq({
|
237
|
+
"$nor" => initial + other
|
238
|
+
})
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "#__deep_copy__" do
|
245
|
+
|
246
|
+
let(:value) do
|
247
|
+
[ 1, 2, 3 ]
|
248
|
+
end
|
249
|
+
|
250
|
+
let(:selection) do
|
251
|
+
{ "$in" => value }
|
252
|
+
end
|
253
|
+
|
254
|
+
let(:selector) do
|
255
|
+
described_class.new
|
256
|
+
end
|
257
|
+
|
258
|
+
before do
|
259
|
+
selector[:field] = selection
|
260
|
+
end
|
261
|
+
|
262
|
+
let(:cloned) do
|
263
|
+
selector.__deep_copy__
|
264
|
+
end
|
265
|
+
|
266
|
+
it "returns an equal copy" do
|
267
|
+
expect(cloned).to eq(selector)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "performs a deep copy" do
|
271
|
+
expect(cloned["field"]).to_not equal(selection)
|
272
|
+
end
|
273
|
+
|
274
|
+
it "clones n levels deep" do
|
275
|
+
expect(cloned["field"]["$in"]).to_not equal(value)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
[ :store, :[]= ].each do |method|
|
280
|
+
|
281
|
+
describe "##{method}" do
|
282
|
+
|
283
|
+
context "when aliases are provided" do
|
284
|
+
|
285
|
+
context "when the alias has no serializer" do
|
286
|
+
|
287
|
+
let(:selector) do
|
288
|
+
described_class.new({ "id" => "_id" })
|
289
|
+
end
|
290
|
+
|
291
|
+
before do
|
292
|
+
selector.send(method, "id", 1)
|
293
|
+
end
|
294
|
+
|
295
|
+
it "stores the field in the selector by database name" do
|
296
|
+
expect(selector["_id"]).to eq(1)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context "when the alias has a serializer" do
|
301
|
+
|
302
|
+
before(:all) do
|
303
|
+
class Field
|
304
|
+
def evolve(object)
|
305
|
+
Integer.evolve(object)
|
306
|
+
end
|
307
|
+
|
308
|
+
def localized?
|
309
|
+
false
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
after(:all) do
|
315
|
+
Object.send(:remove_const, :Field)
|
316
|
+
end
|
317
|
+
|
318
|
+
let(:selector) do
|
319
|
+
described_class.new(
|
320
|
+
{ "id" => "_id" }, { "_id" => Field.new }
|
321
|
+
)
|
322
|
+
end
|
323
|
+
|
324
|
+
it "stores the serialized field in the selector by database name" do
|
325
|
+
selector.send(method, "id", "1")
|
326
|
+
expect(selector["_id"]).to eq(1)
|
327
|
+
end
|
328
|
+
|
329
|
+
it "stores the serialized field when selector is deeply nested" do
|
330
|
+
selector.send(method, "$or", [{'$and' => [{'_id' => '5'}]}])
|
331
|
+
expect(selector['$or'][0]['$and'][0]['_id']).to eq(5)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context "when no serializers are provided" do
|
337
|
+
|
338
|
+
let(:selector) do
|
339
|
+
described_class.new
|
340
|
+
end
|
341
|
+
|
342
|
+
context "when provided a standard object" do
|
343
|
+
|
344
|
+
context "when the keys are strings" do
|
345
|
+
|
346
|
+
it "does not serialize values" do
|
347
|
+
expect(selector.send(method, "key", "5")).to eq("5")
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context "when the keys are symbols" do
|
352
|
+
|
353
|
+
it "does not serialize values" do
|
354
|
+
expect(selector.send(method, :key, "5")).to eq("5")
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
context "when provided a range" do
|
360
|
+
|
361
|
+
before do
|
362
|
+
selector.send(method, "key", 1..3)
|
363
|
+
end
|
364
|
+
|
365
|
+
it "serializes the range" do
|
366
|
+
expect(selector["key"]).to eq({ "$gte" => 1, "$lte" => 3 })
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
context "when providing an array" do
|
371
|
+
|
372
|
+
let(:big_one) do
|
373
|
+
BigDecimal.new("1.2321")
|
374
|
+
end
|
375
|
+
|
376
|
+
let(:big_two) do
|
377
|
+
BigDecimal.new("4.2222")
|
378
|
+
end
|
379
|
+
|
380
|
+
let(:array) do
|
381
|
+
[ big_one, big_two ]
|
382
|
+
end
|
383
|
+
|
384
|
+
before do
|
385
|
+
selector.send(method, "key", array)
|
386
|
+
end
|
387
|
+
|
388
|
+
it "serializes each element in the array" do
|
389
|
+
expect(selector["key"]).to eq([ big_one.to_s, big_two.to_s ])
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
context "when serializers are provided" do
|
395
|
+
|
396
|
+
context "when the serializer is not localized" do
|
397
|
+
|
398
|
+
before(:all) do
|
399
|
+
class Field
|
400
|
+
def evolve(object)
|
401
|
+
Integer.evolve(object)
|
402
|
+
end
|
403
|
+
|
404
|
+
def localized?
|
405
|
+
false
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
after(:all) do
|
411
|
+
Object.send(:remove_const, :Field)
|
412
|
+
end
|
413
|
+
|
414
|
+
let(:selector) do
|
415
|
+
described_class.new({}, { "key" => Field.new })
|
416
|
+
end
|
417
|
+
|
418
|
+
context "when the criterion is simple" do
|
419
|
+
|
420
|
+
context "when the key is a string" do
|
421
|
+
|
422
|
+
before do
|
423
|
+
selector.send(method, "key", "5")
|
424
|
+
end
|
425
|
+
|
426
|
+
it "serializes the value" do
|
427
|
+
expect(selector["key"]).to eq(5)
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context "when the key is a symbol" do
|
432
|
+
|
433
|
+
before do
|
434
|
+
selector.send(method, :key, "5")
|
435
|
+
end
|
436
|
+
|
437
|
+
it "serializes the value" do
|
438
|
+
expect(selector["key"]).to eq(5)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
context "when the criterion is complex" do
|
444
|
+
|
445
|
+
context "when the field name is the key" do
|
446
|
+
|
447
|
+
context "when the criterion is an array" do
|
448
|
+
|
449
|
+
context "when the key is a string" do
|
450
|
+
|
451
|
+
before do
|
452
|
+
selector.send(method, "key", [ "1", "2" ])
|
453
|
+
end
|
454
|
+
|
455
|
+
it "serializes the value" do
|
456
|
+
expect(selector["key"]).to eq([ 1, 2 ])
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
context "when the key is a symbol" do
|
461
|
+
|
462
|
+
before do
|
463
|
+
selector.send(method, :key, [ "1", "2" ])
|
464
|
+
end
|
465
|
+
|
466
|
+
it "serializes the value" do
|
467
|
+
expect(selector["key"]).to eq([ 1, 2 ])
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
context "when the criterion is a hash" do
|
473
|
+
|
474
|
+
context "when the value is non enumerable" do
|
475
|
+
|
476
|
+
context "when the key is a string" do
|
477
|
+
|
478
|
+
before do
|
479
|
+
selector.send(method, "key", { "$gt" => "5" })
|
480
|
+
end
|
481
|
+
|
482
|
+
it "serializes the value" do
|
483
|
+
expect(selector["key"]).to eq({ "$gt" => 5 })
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
context "when the key is a symbol" do
|
488
|
+
|
489
|
+
before do
|
490
|
+
selector.send(method, :key, { "$gt" => "5" })
|
491
|
+
end
|
492
|
+
|
493
|
+
it "serializes the value" do
|
494
|
+
expect(selector["key"]).to eq({ "$gt" => 5 })
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
context "when the value is enumerable" do
|
500
|
+
|
501
|
+
context "when the key is a string" do
|
502
|
+
|
503
|
+
before do
|
504
|
+
selector.send(method, "key", { "$in" => [ "1", "2" ] })
|
505
|
+
end
|
506
|
+
|
507
|
+
it "serializes the value" do
|
508
|
+
expect(selector["key"]).to eq({ "$in" => [ 1, 2 ] })
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
context "when the key is a symbol" do
|
513
|
+
|
514
|
+
before do
|
515
|
+
selector.send(method, :key, { "$in" => [ "1", "2" ] })
|
516
|
+
end
|
517
|
+
|
518
|
+
it "serializes the value" do
|
519
|
+
expect(selector["key"]).to eq({ "$in" => [ 1, 2 ] })
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
[ "$and", "$or" ].each do |operator|
|
525
|
+
|
526
|
+
context "when the criterion is a #{operator}" do
|
527
|
+
|
528
|
+
context "when the individual criteria are simple" do
|
529
|
+
|
530
|
+
context "when the keys are strings" do
|
531
|
+
|
532
|
+
before do
|
533
|
+
selector.send(method, operator, [{ "key" => "1" }])
|
534
|
+
end
|
535
|
+
|
536
|
+
it "serializes the values" do
|
537
|
+
expect(selector[operator]).to eq([{ "key" => 1 }])
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
context "when the keys are symbols" do
|
542
|
+
|
543
|
+
before do
|
544
|
+
selector.send(method, operator, [{ key: "1" }])
|
545
|
+
end
|
546
|
+
|
547
|
+
it "serializes the values" do
|
548
|
+
expect(selector[operator]).to eq([{ "key" => 1 }])
|
549
|
+
end
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
context "when the individual criteria are complex" do
|
554
|
+
|
555
|
+
context "when the keys are strings" do
|
556
|
+
|
557
|
+
before do
|
558
|
+
selector.send(
|
559
|
+
method,
|
560
|
+
operator,
|
561
|
+
[{ "field" => "1" }, { "key" => { "$gt" => "2" }}]
|
562
|
+
)
|
563
|
+
end
|
564
|
+
|
565
|
+
it "serializes the values" do
|
566
|
+
expect(selector[operator]).to eq(
|
567
|
+
[{ "field" => "1" }, { "key" => { "$gt" => 2 }}]
|
568
|
+
)
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
context "when the keys are symbols" do
|
573
|
+
|
574
|
+
before do
|
575
|
+
selector.send(
|
576
|
+
method,
|
577
|
+
operator,
|
578
|
+
[{ field: "1" }, { key: { "$gt" => "2" }}]
|
579
|
+
)
|
580
|
+
end
|
581
|
+
|
582
|
+
it "serializes the values" do
|
583
|
+
expect(selector[operator]).to eq(
|
584
|
+
[{ "field" => "1" }, { "key" => { "$gt" => 2 }}]
|
585
|
+
)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
context "when the serializer is localized" do
|
597
|
+
|
598
|
+
before(:all) do
|
599
|
+
class Field
|
600
|
+
def evolve(object)
|
601
|
+
Integer.evolve(object)
|
602
|
+
end
|
603
|
+
|
604
|
+
def localized?
|
605
|
+
true
|
606
|
+
end
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
after(:all) do
|
611
|
+
Object.send(:remove_const, :Field)
|
612
|
+
::I18n.locale = :en
|
613
|
+
end
|
614
|
+
|
615
|
+
let(:selector) do
|
616
|
+
described_class.new({}, { "key" => Field.new })
|
617
|
+
end
|
618
|
+
|
619
|
+
before do
|
620
|
+
::I18n.locale = :de
|
621
|
+
end
|
622
|
+
|
623
|
+
context "when the criterion is simple" do
|
624
|
+
|
625
|
+
context "when the key is a string" do
|
626
|
+
|
627
|
+
before do
|
628
|
+
selector.send(method, "key", "5")
|
629
|
+
end
|
630
|
+
|
631
|
+
it "serializes the value" do
|
632
|
+
expect(selector["key.de"]).to eq(5)
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
context "when the key is a symbol" do
|
637
|
+
|
638
|
+
before do
|
639
|
+
selector.send(method, :key, "5")
|
640
|
+
end
|
641
|
+
|
642
|
+
it "serializes the value" do
|
643
|
+
expect(selector["key.de"]).to eq(5)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
context "when the criterion is complex" do
|
649
|
+
|
650
|
+
context "when the field name is the key" do
|
651
|
+
|
652
|
+
context "when the criterion is an array" do
|
653
|
+
|
654
|
+
context "when the key is a string" do
|
655
|
+
|
656
|
+
before do
|
657
|
+
selector.send(method, "key", [ "1", "2" ])
|
658
|
+
end
|
659
|
+
|
660
|
+
it "serializes the value" do
|
661
|
+
expect(selector["key.de"]).to eq([ 1, 2 ])
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
context "when the key is a symbol" do
|
666
|
+
|
667
|
+
before do
|
668
|
+
selector.send(method, :key, [ "1", "2" ])
|
669
|
+
end
|
670
|
+
|
671
|
+
it "serializes the value" do
|
672
|
+
expect(selector["key.de"]).to eq([ 1, 2 ])
|
673
|
+
end
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
context "when the criterion is a hash" do
|
678
|
+
|
679
|
+
context "when the value is non enumerable" do
|
680
|
+
|
681
|
+
context "when the key is a string" do
|
682
|
+
|
683
|
+
let(:hash) do
|
684
|
+
{ "$gt" => "5" }
|
685
|
+
end
|
686
|
+
|
687
|
+
before do
|
688
|
+
selector.send(method, "key", hash)
|
689
|
+
end
|
690
|
+
|
691
|
+
it "serializes the value" do
|
692
|
+
expect(selector["key.de"]).to eq({ "$gt" => 5 })
|
693
|
+
end
|
694
|
+
|
695
|
+
it "sets the same hash instance" do
|
696
|
+
expect(selector["key.de"]).to equal(hash)
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
context "when the key is a symbol" do
|
701
|
+
|
702
|
+
before do
|
703
|
+
selector.send(method, :key, { "$gt" => "5" })
|
704
|
+
end
|
705
|
+
|
706
|
+
it "serializes the value" do
|
707
|
+
expect(selector["key.de"]).to eq({ "$gt" => 5 })
|
708
|
+
end
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
712
|
+
context "when the value is enumerable" do
|
713
|
+
|
714
|
+
context "when the key is a string" do
|
715
|
+
|
716
|
+
before do
|
717
|
+
selector.send(method, "key", { "$in" => [ "1", "2" ] })
|
718
|
+
end
|
719
|
+
|
720
|
+
it "serializes the value" do
|
721
|
+
expect(selector["key.de"]).to eq({ "$in" => [ 1, 2 ] })
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
context "when the key is a symbol" do
|
726
|
+
|
727
|
+
before do
|
728
|
+
selector.send(method, :key, { "$in" => [ "1", "2" ] })
|
729
|
+
end
|
730
|
+
|
731
|
+
it "serializes the value" do
|
732
|
+
expect(selector["key.de"]).to eq({ "$in" => [ 1, 2 ] })
|
733
|
+
end
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
[ "$and", "$or" ].each do |operator|
|
738
|
+
|
739
|
+
context "when the criterion is a #{operator}" do
|
740
|
+
|
741
|
+
context "when the individual criteria are simple" do
|
742
|
+
|
743
|
+
context "when the keys are strings" do
|
744
|
+
|
745
|
+
before do
|
746
|
+
selector.send(method, operator, [{ "key" => "1" }])
|
747
|
+
end
|
748
|
+
|
749
|
+
it "serializes the values" do
|
750
|
+
expect(selector[operator]).to eq([{ "key.de" => 1 }])
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
context "when the keys are symbols" do
|
755
|
+
|
756
|
+
before do
|
757
|
+
selector.send(method, operator, [{ key: "1" }])
|
758
|
+
end
|
759
|
+
|
760
|
+
it "serializes the values" do
|
761
|
+
expect(selector[operator]).to eq([{ "key.de" => 1 }])
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
context "when the individual criteria are complex" do
|
767
|
+
|
768
|
+
context "when the keys are strings" do
|
769
|
+
|
770
|
+
before do
|
771
|
+
selector.send(
|
772
|
+
method,
|
773
|
+
operator,
|
774
|
+
[{ "field" => "1" }, { "key" => { "$gt" => "2" }}]
|
775
|
+
)
|
776
|
+
end
|
777
|
+
|
778
|
+
it "serializes the values" do
|
779
|
+
expect(selector[operator]).to eq(
|
780
|
+
[{ "field" => "1" }, { "key.de" => { "$gt" => 2 }}]
|
781
|
+
)
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
context "when the keys are symbols" do
|
786
|
+
|
787
|
+
before do
|
788
|
+
selector.send(
|
789
|
+
method,
|
790
|
+
operator,
|
791
|
+
[{ field: "1" }, { key: { "$gt" => "2" }}]
|
792
|
+
)
|
793
|
+
end
|
794
|
+
|
795
|
+
it "serializes the values" do
|
796
|
+
expect(selector[operator]).to eq(
|
797
|
+
[{ "field" => "1" }, { "key.de" => { "$gt" => 2 }}]
|
798
|
+
)
|
799
|
+
end
|
800
|
+
end
|
801
|
+
end
|
802
|
+
end
|
803
|
+
end
|
804
|
+
end
|
805
|
+
end
|
806
|
+
end
|
807
|
+
end
|
808
|
+
end
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
describe "#to_pipeline" do
|
813
|
+
|
814
|
+
let(:selector) do
|
815
|
+
described_class.new
|
816
|
+
end
|
817
|
+
|
818
|
+
context "when the selector is empty" do
|
819
|
+
|
820
|
+
let(:pipeline) do
|
821
|
+
selector.to_pipeline
|
822
|
+
end
|
823
|
+
|
824
|
+
it "returns an empty array" do
|
825
|
+
expect(pipeline).to be_empty
|
826
|
+
end
|
827
|
+
end
|
828
|
+
|
829
|
+
context "when the selector is not empty" do
|
830
|
+
|
831
|
+
before do
|
832
|
+
selector["name"] = "test"
|
833
|
+
end
|
834
|
+
|
835
|
+
let(:pipeline) do
|
836
|
+
selector.to_pipeline
|
837
|
+
end
|
838
|
+
|
839
|
+
it "returns the selector in a $match entry" do
|
840
|
+
expect(pipeline).to eq([{ "$match" => { "name" => "test" }}])
|
841
|
+
end
|
842
|
+
end
|
843
|
+
end
|
844
|
+
end
|