mongoid 8.0.10 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +3 -3
- data/README.md +3 -3
- data/Rakefile +18 -67
- data/lib/config/locales/en.yml +46 -14
- data/lib/mongoid/association/accessors.rb +3 -7
- data/lib/mongoid/association/builders.rb +1 -1
- data/lib/mongoid/association/eager_loadable.rb +0 -3
- data/lib/mongoid/association/embedded/batchable.rb +2 -2
- data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
- data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
- data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +6 -6
- data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
- data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
- data/lib/mongoid/association/macros.rb +0 -6
- data/lib/mongoid/association/nested/one.rb +40 -2
- data/lib/mongoid/association/proxy.rb +1 -1
- data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +1 -1
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +6 -23
- data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
- data/lib/mongoid/association/reflections.rb +2 -2
- data/lib/mongoid/atomic.rb +7 -16
- data/lib/mongoid/attributes/dynamic.rb +1 -1
- data/lib/mongoid/attributes/nested.rb +2 -2
- data/lib/mongoid/attributes/processing.rb +5 -29
- data/lib/mongoid/attributes/projector.rb +1 -1
- data/lib/mongoid/attributes/readonly.rb +1 -1
- data/lib/mongoid/attributes.rb +8 -2
- data/lib/mongoid/changeable.rb +107 -5
- data/lib/mongoid/clients/storage_options.rb +2 -5
- data/lib/mongoid/clients/validators/storage.rb +1 -13
- data/lib/mongoid/collection_configurable.rb +58 -0
- data/lib/mongoid/composable.rb +2 -0
- data/lib/mongoid/config/defaults.rb +60 -0
- data/lib/mongoid/config/options.rb +0 -3
- data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
- data/lib/mongoid/config/validators.rb +1 -0
- data/lib/mongoid/config.rb +88 -27
- data/lib/mongoid/contextual/atomic.rb +1 -1
- data/lib/mongoid/contextual/memory.rb +233 -33
- data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
- data/lib/mongoid/contextual/mongo.rb +370 -133
- data/lib/mongoid/contextual/none.rb +162 -7
- data/lib/mongoid/contextual.rb +12 -0
- data/lib/mongoid/criteria/findable.rb +2 -2
- data/lib/mongoid/criteria/includable.rb +4 -3
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -15
- data/lib/mongoid/criteria/queryable/key.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
- data/lib/mongoid/criteria/queryable/optional.rb +8 -8
- data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
- data/lib/mongoid/criteria/queryable/selector.rb +1 -1
- data/lib/mongoid/criteria/queryable/storable.rb +1 -1
- data/lib/mongoid/criteria.rb +6 -5
- data/lib/mongoid/deprecable.rb +1 -2
- data/lib/mongoid/deprecation.rb +3 -3
- data/lib/mongoid/document.rb +1 -8
- data/lib/mongoid/errors/create_collection_failure.rb +33 -0
- data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
- data/lib/mongoid/errors/immutable_attribute.rb +26 -0
- data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
- data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
- data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
- data/lib/mongoid/errors.rb +4 -1
- data/lib/mongoid/extensions/hash.rb +2 -24
- data/lib/mongoid/extensions/object.rb +2 -2
- data/lib/mongoid/extensions/time.rb +2 -0
- data/lib/mongoid/fields/localized.rb +10 -0
- data/lib/mongoid/fields/standard.rb +10 -0
- data/lib/mongoid/fields.rb +59 -35
- data/lib/mongoid/findable.rb +27 -3
- data/lib/mongoid/interceptable.rb +6 -116
- data/lib/mongoid/matcher/eq_impl.rb +1 -1
- data/lib/mongoid/matcher/type.rb +1 -1
- data/lib/mongoid/persistable/creatable.rb +1 -0
- data/lib/mongoid/persistable/deletable.rb +1 -1
- data/lib/mongoid/persistable/savable.rb +13 -1
- data/lib/mongoid/persistable/unsettable.rb +2 -2
- data/lib/mongoid/persistable/updatable.rb +51 -1
- data/lib/mongoid/persistable/upsertable.rb +20 -1
- data/lib/mongoid/persistable.rb +3 -0
- data/lib/mongoid/query_cache.rb +5 -1
- data/lib/mongoid/railties/database.rake +7 -2
- data/lib/mongoid/reloadable.rb +5 -3
- data/lib/mongoid/stateful.rb +22 -1
- data/lib/mongoid/tasks/database.rake +12 -0
- data/lib/mongoid/tasks/database.rb +20 -0
- data/lib/mongoid/timestamps/created.rb +1 -8
- data/lib/mongoid/traversable.rb +0 -12
- data/lib/mongoid/utils.rb +22 -0
- data/lib/mongoid/validatable/associated.rb +17 -98
- data/lib/mongoid/validatable/macros.rb +5 -5
- data/lib/mongoid/validatable.rb +4 -9
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/warnings.rb +17 -1
- data/lib/mongoid.rb +16 -3
- data/spec/integration/app_spec.rb +2 -6
- data/spec/integration/associations/has_and_belongs_to_many_spec.rb +0 -40
- data/spec/integration/callbacks_spec.rb +99 -12
- data/spec/integration/discriminator_key_spec.rb +4 -5
- data/spec/integration/i18n_fallbacks_spec.rb +3 -2
- data/spec/mongoid/association/eager_spec.rb +2 -24
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +20 -25
- data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
- data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +0 -4
- data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
- data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +42 -55
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
- data/spec/mongoid/association/syncable_spec.rb +1 -1
- data/spec/mongoid/association_spec.rb +0 -60
- data/spec/mongoid/attributes_spec.rb +3 -33
- data/spec/mongoid/changeable_spec.rb +299 -24
- data/spec/mongoid/clients_spec.rb +122 -13
- data/spec/mongoid/collection_configurable_spec.rb +158 -0
- data/spec/mongoid/config/defaults_spec.rb +160 -0
- data/spec/mongoid/config_spec.rb +154 -27
- data/spec/mongoid/contextual/memory_spec.rb +332 -76
- data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
- data/spec/mongoid/contextual/mongo_spec.rb +1009 -125
- data/spec/mongoid/contextual/none_spec.rb +49 -2
- data/spec/mongoid/copyable_spec.rb +2 -10
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -10
- data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/selector_spec.rb +3 -76
- data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
- data/spec/mongoid/criteria_projection_spec.rb +1 -4
- data/spec/mongoid/criteria_spec.rb +5 -9
- data/spec/mongoid/document_spec.rb +0 -27
- data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
- data/spec/mongoid/extensions/hash_spec.rb +3 -3
- data/spec/mongoid/extensions/time_spec.rb +8 -43
- data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
- data/spec/mongoid/fields/localized_spec.rb +46 -28
- data/spec/mongoid/fields_spec.rb +136 -77
- data/spec/mongoid/findable_spec.rb +391 -34
- data/spec/mongoid/indexable_spec.rb +16 -10
- data/spec/mongoid/interceptable_spec.rb +153 -442
- data/spec/mongoid/interceptable_spec_models.rb +111 -51
- data/spec/mongoid/persistable/deletable_spec.rb +26 -6
- data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
- data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
- data/spec/mongoid/persistable/logical_spec.rb +37 -0
- data/spec/mongoid/persistable/poppable_spec.rb +36 -0
- data/spec/mongoid/persistable/pullable_spec.rb +72 -0
- data/spec/mongoid/persistable/pushable_spec.rb +72 -0
- data/spec/mongoid/persistable/renamable_spec.rb +36 -0
- data/spec/mongoid/persistable/savable_spec.rb +96 -0
- data/spec/mongoid/persistable/settable_spec.rb +37 -0
- data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
- data/spec/mongoid/persistable/updatable_spec.rb +20 -28
- data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
- data/spec/mongoid/persistence_context_spec.rb +7 -57
- data/spec/mongoid/query_cache_spec.rb +56 -61
- data/spec/mongoid/reloadable_spec.rb +24 -28
- data/spec/mongoid/scopable_spec.rb +70 -0
- data/spec/mongoid/serializable_spec.rb +23 -44
- data/spec/mongoid/stateful_spec.rb +122 -8
- data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
- data/spec/mongoid/tasks/database_spec.rb +127 -0
- data/spec/mongoid/timestamps/created_spec.rb +0 -23
- data/spec/mongoid/timestamps_spec.rb +9 -11
- data/spec/mongoid/touchable_spec.rb +277 -5
- data/spec/mongoid/touchable_spec_models.rb +3 -1
- data/spec/mongoid/traversable_spec.rb +9 -24
- data/spec/mongoid/validatable/associated_spec.rb +34 -27
- data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
- data/spec/mongoid_spec.rb +36 -10
- data/spec/shared/LICENSE +20 -0
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
- data/spec/shared/lib/mrss/cluster_config.rb +231 -0
- data/spec/shared/lib/mrss/constraints.rb +378 -0
- data/spec/shared/lib/mrss/docker_runner.rb +298 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
- data/spec/shared/lib/mrss/session_registry.rb +69 -0
- data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
- data/spec/shared/lib/mrss/utils.rb +37 -0
- data/spec/shared/share/Dockerfile.erb +321 -0
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/config.sh +27 -0
- data/spec/shared/shlib/distro.sh +74 -0
- data/spec/shared/shlib/server.sh +416 -0
- data/spec/shared/shlib/set_env.sh +169 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/immutable_ids.rb +118 -0
- data/spec/support/macros.rb +47 -15
- data/spec/support/models/artist.rb +0 -1
- data/spec/support/models/band.rb +1 -0
- data/spec/support/models/building.rb +2 -0
- data/spec/support/models/name.rb +0 -10
- data/spec/support/models/person.rb +0 -1
- data/spec/support/models/product.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +745 -637
- metadata.gz.sig +2 -0
- data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
- data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
- data/spec/support/models/purse.rb +0 -9
@@ -54,8 +54,17 @@ describe Mongoid::Contextual::None do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
describe "#pluck" do
|
57
|
-
|
58
|
-
|
57
|
+
|
58
|
+
context "when plucking one field" do
|
59
|
+
it "returns an empty array" do
|
60
|
+
expect(context.pluck(:id)).to eq([])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when plucking multiple fields" do
|
65
|
+
it "returns an empty array" do
|
66
|
+
expect(context.pluck(:id, :foo)).to eq([])
|
67
|
+
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
@@ -81,6 +90,14 @@ describe Mongoid::Contextual::None do
|
|
81
90
|
end
|
82
91
|
end
|
83
92
|
|
93
|
+
describe "#first!" do
|
94
|
+
it "raises an error" do
|
95
|
+
expect do
|
96
|
+
context.first!
|
97
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
84
101
|
describe "#last" do
|
85
102
|
it "returns nil" do
|
86
103
|
expect(context.last).to be_nil
|
@@ -91,6 +108,14 @@ describe Mongoid::Contextual::None do
|
|
91
108
|
end
|
92
109
|
end
|
93
110
|
|
111
|
+
describe "#last!" do
|
112
|
+
it "raises an error" do
|
113
|
+
expect do
|
114
|
+
context.last!
|
115
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
94
119
|
describe "#take" do
|
95
120
|
it "returns nil" do
|
96
121
|
expect(context.take).to be_nil
|
@@ -109,6 +134,28 @@ describe Mongoid::Contextual::None do
|
|
109
134
|
end
|
110
135
|
end
|
111
136
|
|
137
|
+
[ :second,
|
138
|
+
:third,
|
139
|
+
:fourth,
|
140
|
+
:fifth,
|
141
|
+
:second_to_last,
|
142
|
+
:third_to_last
|
143
|
+
].each do |meth|
|
144
|
+
describe "##{meth}" do
|
145
|
+
it "returns nil" do
|
146
|
+
expect(context.send(meth)).to be_nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "##{meth}!" do
|
151
|
+
it "raises an error" do
|
152
|
+
expect do
|
153
|
+
context.send("#{meth}!")
|
154
|
+
end.to raise_error(Mongoid::Errors::DocumentNotFound, /Could not find a document of class Band./)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
112
159
|
describe "#length" do
|
113
160
|
it "returns zero" do
|
114
161
|
expect(context.length).to eq(0)
|
@@ -164,19 +164,15 @@ describe Mongoid::Copyable do
|
|
164
164
|
end
|
165
165
|
|
166
166
|
context "when cloning a document with multiple languages field" do
|
167
|
+
with_default_i18n_configs
|
167
168
|
|
168
169
|
before do
|
169
|
-
I18n.enforce_available_locales = false
|
170
170
|
I18n.locale = 'pt_BR'
|
171
171
|
person.desc = "descrição"
|
172
172
|
person.addresses.first.name = "descrição"
|
173
173
|
person.save!
|
174
174
|
end
|
175
175
|
|
176
|
-
after do
|
177
|
-
I18n.locale = :en
|
178
|
-
end
|
179
|
-
|
180
176
|
let!(:from_db) do
|
181
177
|
Person.find(person.id)
|
182
178
|
end
|
@@ -212,22 +208,18 @@ describe Mongoid::Copyable do
|
|
212
208
|
end
|
213
209
|
|
214
210
|
context "when cloning a document with polymorphic embedded documents with multiple language field" do
|
211
|
+
with_default_i18n_configs
|
215
212
|
|
216
213
|
let!(:shipment_address) do
|
217
214
|
person.addresses.build({ shipping_name: "Title" }, ShipmentAddress)
|
218
215
|
end
|
219
216
|
|
220
217
|
before do
|
221
|
-
I18n.enforce_available_locales = false
|
222
218
|
I18n.locale = 'pt_BR'
|
223
219
|
person.addresses.type(ShipmentAddress).each { |address| address.shipping_name = "Título" }
|
224
220
|
person.save!
|
225
221
|
end
|
226
222
|
|
227
|
-
after do
|
228
|
-
I18n.locale = :en
|
229
|
-
end
|
230
|
-
|
231
223
|
let!(:from_db) do
|
232
224
|
Person.find(person.id)
|
233
225
|
end
|
@@ -72,11 +72,8 @@ describe String do
|
|
72
72
|
context "when the string without timezone" do
|
73
73
|
|
74
74
|
context "when using active support's time zone" do
|
75
|
-
|
76
|
-
|
77
|
-
Mongoid.use_activesupport_time_zone = true
|
78
|
-
::Time.zone = "Tokyo"
|
79
|
-
end
|
75
|
+
config_override :use_activesupport_time_zone, true
|
76
|
+
time_zone_override "Tokyo"
|
80
77
|
|
81
78
|
let(:date) do
|
82
79
|
"2010-01-01 5:00:00"
|
@@ -92,11 +89,8 @@ describe String do
|
|
92
89
|
end
|
93
90
|
|
94
91
|
context "when not using active support's time zone" do
|
95
|
-
|
96
|
-
|
97
|
-
Mongoid.use_activesupport_time_zone = false
|
98
|
-
::Time.zone = nil
|
99
|
-
end
|
92
|
+
config_override :use_activesupport_time_zone, false
|
93
|
+
time_zone_override nil
|
100
94
|
|
101
95
|
let(:date) do
|
102
96
|
"2010-01-01 5:00:00"
|
@@ -221,6 +221,7 @@ describe Mongoid::Criteria::Queryable::Options do
|
|
221
221
|
end
|
222
222
|
|
223
223
|
context "when the serializer is localized" do
|
224
|
+
with_default_i18n_configs
|
224
225
|
|
225
226
|
before(:all) do
|
226
227
|
class Field
|
@@ -232,7 +233,6 @@ describe Mongoid::Criteria::Queryable::Options do
|
|
232
233
|
|
233
234
|
after(:all) do
|
234
235
|
Object.send(:remove_const, :Field)
|
235
|
-
::I18n.locale = :en
|
236
236
|
end
|
237
237
|
|
238
238
|
let(:options) do
|
@@ -2116,4 +2116,423 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
2116
2116
|
end
|
2117
2117
|
end
|
2118
2118
|
end
|
2119
|
+
|
2120
|
+
describe "#none_of" do
|
2121
|
+
context 'when argument is a mix of Criteria and hashes' do
|
2122
|
+
let(:query) { Mongoid::Query.new.where(hello: 'world') }
|
2123
|
+
let(:other1) { Mongoid::Query.new.where(foo: 'bar') }
|
2124
|
+
let(:other2) { { bar: 42 } }
|
2125
|
+
let(:other3) { Mongoid::Query.new.where(a: 2) }
|
2126
|
+
|
2127
|
+
let(:result) { query.none_of(other1, other2, other3) }
|
2128
|
+
|
2129
|
+
it 'combines' do
|
2130
|
+
expect(result.selector).to eq(
|
2131
|
+
'hello' => 'world',
|
2132
|
+
'$nor' => [
|
2133
|
+
{'foo' => 'bar'},
|
2134
|
+
{'bar' => 42},
|
2135
|
+
{'a' => 2},
|
2136
|
+
],
|
2137
|
+
)
|
2138
|
+
end
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
context "when provided no arguments" do
|
2142
|
+
let(:selection) { query.none_of }
|
2143
|
+
|
2144
|
+
it_behaves_like 'returns a cloned query'
|
2145
|
+
|
2146
|
+
it "does not add any criteria" do
|
2147
|
+
expect(selection.selector).to eq({})
|
2148
|
+
end
|
2149
|
+
|
2150
|
+
it "returns the query" do
|
2151
|
+
expect(selection).to eq(query)
|
2152
|
+
end
|
2153
|
+
end
|
2154
|
+
|
2155
|
+
context "when provided nil" do
|
2156
|
+
let(:selection) { query.none_of(nil) }
|
2157
|
+
|
2158
|
+
it_behaves_like 'returns a cloned query'
|
2159
|
+
|
2160
|
+
it "does not add any criteria" do
|
2161
|
+
expect(selection.selector).to eq({})
|
2162
|
+
end
|
2163
|
+
|
2164
|
+
it "returns the query" do
|
2165
|
+
expect(selection).to eq(query)
|
2166
|
+
end
|
2167
|
+
end
|
2168
|
+
|
2169
|
+
context "when provided a single criterion" do
|
2170
|
+
let(:selection) { query.none_of(field: [ 1, 2 ]) }
|
2171
|
+
|
2172
|
+
it_behaves_like 'returns a cloned query'
|
2173
|
+
|
2174
|
+
it 'adds the $nor selector' do
|
2175
|
+
expect(selection.selector).to eq(
|
2176
|
+
'$nor' => [ { 'field' => [ 1, 2 ] } ],
|
2177
|
+
)
|
2178
|
+
end
|
2179
|
+
|
2180
|
+
context 'when the criterion is wrapped in array' do
|
2181
|
+
let(:selection) { query.none_of([{ field: [ 1, 2 ] }]) }
|
2182
|
+
|
2183
|
+
it_behaves_like 'returns a cloned query'
|
2184
|
+
|
2185
|
+
it 'adds the condition' do
|
2186
|
+
expect(selection.selector).to eq(
|
2187
|
+
'$nor' => [ { 'field' => [ 1, 2 ] } ],
|
2188
|
+
)
|
2189
|
+
end
|
2190
|
+
|
2191
|
+
context 'when the array has nil as one of the elements' do
|
2192
|
+
let(:selection) { query.none_of([{ field: [ 1, 2 ] }, nil]) }
|
2193
|
+
|
2194
|
+
it_behaves_like 'returns a cloned query'
|
2195
|
+
|
2196
|
+
it 'adds the $nor selector ignoring the nil element' do
|
2197
|
+
expect(selection.selector).to eq(
|
2198
|
+
'$nor' => [ { 'field' => [ 1, 2 ] } ],
|
2199
|
+
)
|
2200
|
+
end
|
2201
|
+
end
|
2202
|
+
end
|
2203
|
+
|
2204
|
+
context 'when query already has a condition on another field' do
|
2205
|
+
context 'when there is one argument' do
|
2206
|
+
let(:selection) { query.where(foo: 'bar').none_of(field: [ 1, 2 ]) }
|
2207
|
+
|
2208
|
+
it 'adds the new condition' do
|
2209
|
+
expect(selection.selector).to eq(
|
2210
|
+
'foo' => 'bar',
|
2211
|
+
'$nor' => [ { 'field' => [1, 2] } ],
|
2212
|
+
)
|
2213
|
+
end
|
2214
|
+
end
|
2215
|
+
|
2216
|
+
context 'when there are multiple arguments' do
|
2217
|
+
let(:selection) do
|
2218
|
+
query.where(foo: 'bar').none_of({ field: [ 1, 2 ] }, { hello: 'world' })
|
2219
|
+
end
|
2220
|
+
|
2221
|
+
it 'adds the new condition' do
|
2222
|
+
expect(selection.selector).to eq(
|
2223
|
+
'foo' => 'bar',
|
2224
|
+
'$nor' => [
|
2225
|
+
{ 'field' => [1, 2] },
|
2226
|
+
{ 'hello' => 'world' },
|
2227
|
+
],
|
2228
|
+
)
|
2229
|
+
end
|
2230
|
+
end
|
2231
|
+
end
|
2232
|
+
|
2233
|
+
context 'when query already has a $nor condition and another condition' do
|
2234
|
+
let(:selection) do
|
2235
|
+
query.nor(field: [ 1, 2 ]).where(foo: 'bar').none_of(test: 1)
|
2236
|
+
end
|
2237
|
+
|
2238
|
+
it 'adds the new condition' do
|
2239
|
+
expect(selection.selector).to eq(
|
2240
|
+
'$nor' => [ { 'field' => [1, 2] } ],
|
2241
|
+
'foo' => 'bar',
|
2242
|
+
'$and' => [ { '$nor' => [ { 'test' => 1 } ] } ]
|
2243
|
+
)
|
2244
|
+
end
|
2245
|
+
end
|
2246
|
+
|
2247
|
+
context 'when none_of has multiple arguments' do
|
2248
|
+
let(:selection) do
|
2249
|
+
query.nor(field: [ 1, 2 ]).where(foo: 'bar').none_of({a: 1}, {b: 2})
|
2250
|
+
end
|
2251
|
+
|
2252
|
+
it 'adds the new condition to top level' do
|
2253
|
+
expect(selection.selector).to eq(
|
2254
|
+
'foo' => 'bar',
|
2255
|
+
'$nor' => [ { 'field' => [1, 2] } ],
|
2256
|
+
'$and' => [ { '$nor' => [ { 'a' => 1 }, { 'b' => 2 } ] } ]
|
2257
|
+
)
|
2258
|
+
end
|
2259
|
+
|
2260
|
+
context 'when query already has a top-level $and' do
|
2261
|
+
let(:selection) do
|
2262
|
+
query.nor(field: [ 1, 2 ]).where('$and' => [foo: 'bar']).none_of({a: 1}, {b: 2})
|
2263
|
+
end
|
2264
|
+
|
2265
|
+
it 'adds the new condition to top level $and' do
|
2266
|
+
expect(selection.selector).to eq(
|
2267
|
+
'$nor' => [ { 'field' => [1, 2] } ],
|
2268
|
+
'$and' => [
|
2269
|
+
{ 'foo' => 'bar' },
|
2270
|
+
{ '$nor' => [ { 'a' => 1 }, { 'b' => 2 } ] }
|
2271
|
+
],
|
2272
|
+
)
|
2273
|
+
end
|
2274
|
+
end
|
2275
|
+
end
|
2276
|
+
end
|
2277
|
+
|
2278
|
+
context "when provided multiple criteria" do
|
2279
|
+
context "when the criteria are for different fields" do
|
2280
|
+
let(:selection) do
|
2281
|
+
query.none_of({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
|
2282
|
+
end
|
2283
|
+
|
2284
|
+
it_behaves_like 'returns a cloned query'
|
2285
|
+
|
2286
|
+
it "adds the $nor selector" do
|
2287
|
+
expect(selection.selector).to eq({
|
2288
|
+
"$nor" => [
|
2289
|
+
{ "first" => [ 1, 2 ] },
|
2290
|
+
{ "second" => [ 3, 4 ] }
|
2291
|
+
]
|
2292
|
+
})
|
2293
|
+
end
|
2294
|
+
end
|
2295
|
+
|
2296
|
+
context "when the criteria uses a Key instance" do
|
2297
|
+
let(:selection) do
|
2298
|
+
query.none_of({ first: [ 1, 2 ] }, { :second.gt => 3 })
|
2299
|
+
end
|
2300
|
+
|
2301
|
+
it "adds the $nor selector" do
|
2302
|
+
expect(selection.selector).to eq({
|
2303
|
+
"$nor" => [
|
2304
|
+
{ "first" => [ 1, 2 ] },
|
2305
|
+
{ "second" => { "$gt" => 3 }}
|
2306
|
+
]
|
2307
|
+
})
|
2308
|
+
end
|
2309
|
+
|
2310
|
+
it_behaves_like 'returns a cloned query'
|
2311
|
+
end
|
2312
|
+
|
2313
|
+
context 'when criteria are simple and handled via Key' do
|
2314
|
+
shared_examples_for 'adds conditions with $nor' do
|
2315
|
+
it "adds conditions with $nor" do
|
2316
|
+
expect(selection.selector).to eq({
|
2317
|
+
'$nor' => [
|
2318
|
+
{'field' => 3},
|
2319
|
+
{'field' => {'$lt' => 5}},
|
2320
|
+
],
|
2321
|
+
})
|
2322
|
+
end
|
2323
|
+
|
2324
|
+
it_behaves_like 'returns a cloned query'
|
2325
|
+
end
|
2326
|
+
|
2327
|
+
shared_examples_for 'combines conditions with $eq' do
|
2328
|
+
it "combines conditions with $eq" do
|
2329
|
+
expect(selection.selector).to eq({
|
2330
|
+
'$nor' => [ { 'field' => { '$eq' => 3, '$lt' => 5 } } ]
|
2331
|
+
})
|
2332
|
+
end
|
2333
|
+
|
2334
|
+
it_behaves_like 'returns a cloned query'
|
2335
|
+
end
|
2336
|
+
|
2337
|
+
shared_examples_for 'combines conditions with $regex' do
|
2338
|
+
it 'combines conditions with $regex' do
|
2339
|
+
expect(selection.selector).to eq({
|
2340
|
+
'$nor' => [ { 'field' => { '$regex' => /t/, '$lt' => 5 } } ]
|
2341
|
+
})
|
2342
|
+
end
|
2343
|
+
|
2344
|
+
it_behaves_like 'returns a cloned query'
|
2345
|
+
end
|
2346
|
+
|
2347
|
+
context 'criteria are provided in the same hash' do
|
2348
|
+
context 'non-regexp argument' do
|
2349
|
+
let(:selection) { query.none_of(:field => 3, :field.lt => 5) }
|
2350
|
+
it_behaves_like 'combines conditions with $eq'
|
2351
|
+
end
|
2352
|
+
|
2353
|
+
context 'regexp argument' do
|
2354
|
+
let(:selection) { query.none_of(:field => /t/, :field.lt => 5) }
|
2355
|
+
it_behaves_like 'combines conditions with $regex'
|
2356
|
+
end
|
2357
|
+
end
|
2358
|
+
|
2359
|
+
context 'criteria are provided in separate hashes' do
|
2360
|
+
let(:selection) { query.none_of({:field => 3}, {:field.lt => 5}) }
|
2361
|
+
it_behaves_like 'adds conditions with $nor'
|
2362
|
+
end
|
2363
|
+
|
2364
|
+
context 'when the criterion is wrapped in an array' do
|
2365
|
+
let(:selection) { query.none_of([:field => 3], [:field.lt => 5]) }
|
2366
|
+
it_behaves_like 'adds conditions with $nor'
|
2367
|
+
end
|
2368
|
+
end
|
2369
|
+
|
2370
|
+
context 'when criteria are handled via Key and simple' do
|
2371
|
+
shared_examples_for 'adds conditions with $nor' do
|
2372
|
+
it 'adds conditions with $nor' do
|
2373
|
+
expect(selection.selector).to eq({
|
2374
|
+
'$nor' => [
|
2375
|
+
{ 'field' => { '$gt' => 3 } },
|
2376
|
+
{ 'field' => 5 },
|
2377
|
+
],
|
2378
|
+
})
|
2379
|
+
end
|
2380
|
+
|
2381
|
+
it_behaves_like 'returns a cloned query'
|
2382
|
+
end
|
2383
|
+
|
2384
|
+
shared_examples_for 'combines conditions with $eq' do
|
2385
|
+
it 'combines conditions with $eq' do
|
2386
|
+
expect(selection.selector).to eq(
|
2387
|
+
'$nor' => [ { 'field' => {'$gt' => 3, '$eq' => 5} } ],
|
2388
|
+
)
|
2389
|
+
end
|
2390
|
+
|
2391
|
+
it_behaves_like 'returns a cloned query'
|
2392
|
+
end
|
2393
|
+
|
2394
|
+
shared_examples_for 'combines conditions with $regex' do
|
2395
|
+
it 'combines conditions with $regex' do
|
2396
|
+
expect(selection.selector).to eq(
|
2397
|
+
'$nor' => [ { 'field' => {'$gt' => 3, '$regex' => /t/} } ],
|
2398
|
+
)
|
2399
|
+
end
|
2400
|
+
|
2401
|
+
it_behaves_like 'returns a cloned query'
|
2402
|
+
end
|
2403
|
+
|
2404
|
+
context 'criteria are provided in the same hash' do
|
2405
|
+
context 'non-regexp argument' do
|
2406
|
+
let(:selection) { query.none_of(:field.gt => 3, :field => 5) }
|
2407
|
+
it_behaves_like 'combines conditions with $eq'
|
2408
|
+
end
|
2409
|
+
|
2410
|
+
context 'regexp argument' do
|
2411
|
+
let(:selection) { query.none_of(:field.gt => 3, :field => /t/) }
|
2412
|
+
it_behaves_like 'combines conditions with $regex'
|
2413
|
+
end
|
2414
|
+
end
|
2415
|
+
|
2416
|
+
context 'criteria are provided in separate hashes' do
|
2417
|
+
let(:selection) { query.none_of({:field.gt => 3}, {:field => 5}) }
|
2418
|
+
it_behaves_like 'adds conditions with $nor'
|
2419
|
+
end
|
2420
|
+
|
2421
|
+
context 'when the criterion is wrapped in an array' do
|
2422
|
+
let(:selection) { query.none_of([:field.gt => 3], [:field => 5]) }
|
2423
|
+
it_behaves_like 'adds conditions with $nor'
|
2424
|
+
end
|
2425
|
+
end
|
2426
|
+
|
2427
|
+
context 'when a criterion has an aliased field' do
|
2428
|
+
let(:selection) { query.none_of({ id: 1 }) }
|
2429
|
+
|
2430
|
+
it 'adds the $nor selector and aliases the field' do
|
2431
|
+
expect(selection.selector).to eq('$nor' => [{ '_id' => 1 }])
|
2432
|
+
end
|
2433
|
+
|
2434
|
+
it_behaves_like 'returns a cloned query'
|
2435
|
+
end
|
2436
|
+
|
2437
|
+
context 'when a criterion is wrapped in an array' do
|
2438
|
+
let(:selection) do
|
2439
|
+
query.none_of([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
|
2440
|
+
end
|
2441
|
+
|
2442
|
+
it_behaves_like 'returns a cloned query'
|
2443
|
+
|
2444
|
+
it 'adds the $ nor selector' do
|
2445
|
+
expect(selection.selector).to eq({
|
2446
|
+
'$nor' => [
|
2447
|
+
{ 'first' => [ 1, 2 ] },
|
2448
|
+
{ 'second' => { '$gt' => 3 }}
|
2449
|
+
]
|
2450
|
+
})
|
2451
|
+
end
|
2452
|
+
end
|
2453
|
+
|
2454
|
+
context "when the criteria are on the same field" do
|
2455
|
+
let(:selection) do
|
2456
|
+
query.none_of({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
|
2457
|
+
end
|
2458
|
+
|
2459
|
+
it_behaves_like 'returns a cloned query'
|
2460
|
+
|
2461
|
+
it 'appends both $nor expressions' do
|
2462
|
+
expect(selection.selector).to eq({
|
2463
|
+
"$nor" => [
|
2464
|
+
{ "first" => [ 1, 2 ] },
|
2465
|
+
{ "first" => [ 3, 4 ] }
|
2466
|
+
]
|
2467
|
+
})
|
2468
|
+
end
|
2469
|
+
end
|
2470
|
+
end
|
2471
|
+
|
2472
|
+
context 'when chaining the criteria' do
|
2473
|
+
context 'when the criteria are for different fields' do
|
2474
|
+
let(:selection) do
|
2475
|
+
query.none_of(first: [ 1, 2 ]).none_of(second: [ 3, 4 ])
|
2476
|
+
end
|
2477
|
+
|
2478
|
+
it_behaves_like 'returns a cloned query'
|
2479
|
+
|
2480
|
+
it 'adds the conditions separately' do
|
2481
|
+
expect(selection.selector).to eq(
|
2482
|
+
'$nor' => [ { 'first' => [ 1, 2 ] } ],
|
2483
|
+
'$and' => [ { '$nor' => [ { 'second' => [ 3, 4 ] } ] } ],
|
2484
|
+
)
|
2485
|
+
end
|
2486
|
+
end
|
2487
|
+
|
2488
|
+
context "when the criteria are on the same field" do
|
2489
|
+
let(:selection) do
|
2490
|
+
query.none_of(first: [ 1, 2 ]).none_of(first: [ 3, 4 ])
|
2491
|
+
end
|
2492
|
+
|
2493
|
+
it_behaves_like 'returns a cloned query'
|
2494
|
+
|
2495
|
+
it 'adds the conditions separately' do
|
2496
|
+
expect(selection.selector).to eq(
|
2497
|
+
'$nor' => [ { 'first' => [ 1, 2 ] } ],
|
2498
|
+
'$and' => [ { '$nor' => [ { 'first' => [ 3, 4 ] } ] } ]
|
2499
|
+
)
|
2500
|
+
end
|
2501
|
+
end
|
2502
|
+
end
|
2503
|
+
|
2504
|
+
context 'when using multiple criteria and symbol operators' do
|
2505
|
+
context 'when using fields that meaningfully evolve values' do
|
2506
|
+
let(:query) do
|
2507
|
+
Dictionary.none_of({a: 1}, :published.gt => Date.new(2020, 2, 3))
|
2508
|
+
end
|
2509
|
+
|
2510
|
+
it 'generates the expected query' do
|
2511
|
+
query.selector.should == {'$nor' => [
|
2512
|
+
{'a' => 1},
|
2513
|
+
# Date instance is converted to a Time instance in local time,
|
2514
|
+
# because we are querying on a Time field and dates are interpreted
|
2515
|
+
# in local time when assigning to Time fields
|
2516
|
+
{'published' => {'$gt' => Time.local(2020, 2, 3) } },
|
2517
|
+
] }
|
2518
|
+
end
|
2519
|
+
end
|
2520
|
+
|
2521
|
+
context 'when using fields that do not meaningfully evolve values' do
|
2522
|
+
let(:query) do
|
2523
|
+
Dictionary.none_of({a: 1}, :submitted_on.gt => Date.new(2020, 2, 3))
|
2524
|
+
end
|
2525
|
+
|
2526
|
+
it 'generates the expected query' do
|
2527
|
+
query.selector.should == {'$nor' => [
|
2528
|
+
{'a' => 1},
|
2529
|
+
# Date instance is converted to a Time instance in UTC,
|
2530
|
+
# because we are querying on a Date field and dates are interpreted
|
2531
|
+
# in UTC when persisted as dates by Mongoid
|
2532
|
+
{'submitted_on' => {'$gt' => Time.utc(2020, 2, 3)}},
|
2533
|
+
]}
|
2534
|
+
end
|
2535
|
+
end
|
2536
|
+
end
|
2537
|
+
end
|
2119
2538
|
end
|
@@ -2045,7 +2045,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
|
|
2045
2045
|
end
|
2046
2046
|
|
2047
2047
|
# MongoDB server can only handle one text expression at a time,
|
2048
|
-
# per https://
|
2048
|
+
# per https://www.mongodb.com/docs/manual/reference/operator/query/text/.
|
2049
2049
|
# Nonetheless we test that the query is built correctly when
|
2050
2050
|
# a user supplies more than one text condition.
|
2051
2051
|
it 'merges conditions' do
|