mongoid 8.1.2 → 8.1.4
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/lib/mongoid/association/embedded/embeds_many/proxy.rb +18 -3
- data/lib/mongoid/association/referenced/has_many/proxy.rb +11 -2
- data/lib/mongoid/config.rb +13 -0
- data/lib/mongoid/contextual/mongo.rb +24 -1
- data/lib/mongoid/deprecable.rb +2 -1
- data/lib/mongoid/deprecation.rb +3 -3
- data/lib/mongoid/extensions/hash.rb +19 -1
- data/lib/mongoid/interceptable.rb +116 -7
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/callbacks_spec.rb +21 -0
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +35 -0
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +42 -0
- data/spec/mongoid/contextual/mongo_spec.rb +51 -6
- data/spec/mongoid/interceptable_spec.rb +364 -153
- data/spec/shared/lib/mrss/docker_runner.rb +8 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +2 -2
- data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
- data/spec/shared/lib/mrss/utils.rb +28 -6
- data/spec/shared/share/Dockerfile.erb +36 -40
- data/spec/shared/shlib/server.sh +28 -4
- data/spec/shared/shlib/set_env.sh +4 -4
- data.tar.gz.sig +0 -0
- metadata +5 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '059cd4652349083d2098577aa1c6f1f90233ab91474ef0a3f97db4bef4843f9f'
|
4
|
+
data.tar.gz: ca14035b9902221fe082862ea061f83beb2abc41a9a3eeb10dd0f781a34e697e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 358e801040678c844022e9e41bcdd3a5d482cbafbe608b623340c834d4b72545df547afa83d861d64431703d198c4347f6d9bada41c2960d38b46fdc1a243855
|
7
|
+
data.tar.gz: 8a2981f0a6d4bb4b2c24b6a636079ad3e3cbd1586791104deca7c118d0a08f8753a9a2ce564b416293ce337154c965f26a9ce34f44f087dd0fa8c981d58684da
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -227,9 +227,24 @@ module Mongoid
|
|
227
227
|
# @example Are there persisted documents?
|
228
228
|
# person.posts.exists?
|
229
229
|
#
|
230
|
-
# @
|
231
|
-
|
232
|
-
|
230
|
+
# @param [ :none | nil | false | Hash | Object ] id_or_conditions
|
231
|
+
# When :none (the default), returns true if any persisted
|
232
|
+
# documents exist in the association. When nil or false, this
|
233
|
+
# will always return false. When a Hash is given, this queries
|
234
|
+
# the documents in the association for those that match the given
|
235
|
+
# conditions, and returns true if any match which have been
|
236
|
+
# persisted. Any other argument is interpreted as an id, and
|
237
|
+
# queries for the existence of persisted documents in the
|
238
|
+
# association with a matching _id.
|
239
|
+
#
|
240
|
+
# @return [ true | false ] True if persisted documents exist, false if not.
|
241
|
+
def exists?(id_or_conditions = :none)
|
242
|
+
case id_or_conditions
|
243
|
+
when :none then _target.any?(&:persisted?)
|
244
|
+
when nil, false then false
|
245
|
+
when Hash then where(id_or_conditions).any?(&:persisted?)
|
246
|
+
else where(_id: id_or_conditions).any?(&:persisted?)
|
247
|
+
end
|
233
248
|
end
|
234
249
|
|
235
250
|
# Finds a document in this association through several different
|
@@ -172,9 +172,18 @@ module Mongoid
|
|
172
172
|
# @example Are there persisted documents?
|
173
173
|
# person.posts.exists?
|
174
174
|
#
|
175
|
+
# @param [ :none | nil | false | Hash | Object ] id_or_conditions
|
176
|
+
# When :none (the default), returns true if any persisted
|
177
|
+
# documents exist in the association. When nil or false, this
|
178
|
+
# will always return false. When a Hash is given, this queries
|
179
|
+
# the documents in the association for those that match the given
|
180
|
+
# conditions, and returns true if any match. Any other argument is
|
181
|
+
# interpreted as an id, and queries for the existence of documents
|
182
|
+
# in the association with a matching _id.
|
183
|
+
#
|
175
184
|
# @return [ true | false ] True is persisted documents exist, false if not.
|
176
|
-
def exists?
|
177
|
-
criteria.exists?
|
185
|
+
def exists?(id_or_conditions = :none)
|
186
|
+
criteria.exists?(id_or_conditions)
|
178
187
|
end
|
179
188
|
|
180
189
|
# Find the matching document on the association, either based on id or
|
data/lib/mongoid/config.rb
CHANGED
@@ -185,6 +185,19 @@ module Mongoid
|
|
185
185
|
# See https://jira.mongodb.org/browse/MONGOID-5542
|
186
186
|
option :prevent_multiple_calls_of_embedded_callbacks, default: false
|
187
187
|
|
188
|
+
# When this flag is true, callbacks for embedded documents will not be
|
189
|
+
# called. This is the default in 8.x, but will be changed to false in 9.0.
|
190
|
+
#
|
191
|
+
# Setting this flag to true (as it is in 8.x) may lead to stack
|
192
|
+
# overflow errors if there are more than cicrca 1000 embedded
|
193
|
+
# documents in the root document's dependencies graph.
|
194
|
+
#
|
195
|
+
# It is strongly recommended to set this flag to false in 8.x, if you
|
196
|
+
# are not using around callbacks for embedded documents.
|
197
|
+
#
|
198
|
+
# See https://jira.mongodb.org/browse/MONGOID-5658 for more details.
|
199
|
+
option :around_callbacks_for_embeds, default: true
|
200
|
+
|
188
201
|
# Returns the Config singleton, for use in the configure DSL.
|
189
202
|
#
|
190
203
|
# @return [ self ] The Config singleton.
|
@@ -69,7 +69,12 @@ module Mongoid
|
|
69
69
|
# @return [ Integer ] The number of matches.
|
70
70
|
def count(options = {}, &block)
|
71
71
|
return super(&block) if block_given?
|
72
|
-
|
72
|
+
|
73
|
+
if valid_for_count_documents?
|
74
|
+
view.count_documents(options)
|
75
|
+
else
|
76
|
+
view.count(options)
|
77
|
+
end
|
73
78
|
end
|
74
79
|
|
75
80
|
# Get the estimated number of documents matching the query.
|
@@ -1046,6 +1051,24 @@ module Mongoid
|
|
1046
1051
|
limit ? docs : docs.first
|
1047
1052
|
end
|
1048
1053
|
|
1054
|
+
# Queries whether the current context is valid for use with
|
1055
|
+
# the #count_documents? predicate. A context is valid if it
|
1056
|
+
# does not include a `$where` operator.
|
1057
|
+
#
|
1058
|
+
# @return [ true | false ] whether or not the current context
|
1059
|
+
# excludes a `$where` operator.
|
1060
|
+
def valid_for_count_documents?(hash = view.filter)
|
1061
|
+
# Note that `view.filter` is a BSON::Document, and all keys in a
|
1062
|
+
# BSON::Document are strings; we don't need to worry about symbol
|
1063
|
+
# representations of `$where`.
|
1064
|
+
hash.keys.each do |key|
|
1065
|
+
return false if key == '$where'
|
1066
|
+
return false if hash[key].is_a?(Hash) && !valid_for_count_documents?(hash[key])
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
true
|
1070
|
+
end
|
1071
|
+
|
1049
1072
|
def raise_document_not_found_error
|
1050
1073
|
raise Errors::DocumentNotFound.new(klass, nil, nil)
|
1051
1074
|
end
|
data/lib/mongoid/deprecable.rb
CHANGED
@@ -27,7 +27,8 @@ module Mongoid
|
|
27
27
|
# @param [ [ Symbol | Hash<Symbol, [ Symbol | String ]> ]... ] *method_descriptors
|
28
28
|
# The methods to deprecate, with optional replacement instructions.
|
29
29
|
def deprecate(target_module, *method_descriptors)
|
30
|
-
Mongoid::Deprecation.
|
30
|
+
@_deprecator ||= Mongoid::Deprecation.new
|
31
|
+
@_deprecator.deprecate_methods(target_module, *method_descriptors)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
data/lib/mongoid/deprecation.rb
CHANGED
@@ -15,10 +15,10 @@ module Mongoid
|
|
15
15
|
#
|
16
16
|
# @return Array<Proc> The deprecation behavior.
|
17
17
|
def behavior
|
18
|
-
@behavior ||= Array(->(
|
18
|
+
@behavior ||= Array(->(*args) {
|
19
19
|
logger = Mongoid.logger
|
20
|
-
logger.warn(
|
21
|
-
logger.debug(
|
20
|
+
logger.warn(args[0])
|
21
|
+
logger.debug(args[1].join("\n ")) if debug
|
22
22
|
})
|
23
23
|
end
|
24
24
|
end
|
@@ -43,7 +43,7 @@ module Mongoid
|
|
43
43
|
real_key = klass.database_field_name(key2)
|
44
44
|
|
45
45
|
value.delete(key2) if real_key != key2
|
46
|
-
value[real_key] = (key
|
46
|
+
value[real_key] = value_for(key, klass, real_key, value2)
|
47
47
|
end
|
48
48
|
consolidated[key] ||= {}
|
49
49
|
consolidated[key].update(value)
|
@@ -185,6 +185,24 @@ module Mongoid
|
|
185
185
|
|
186
186
|
private
|
187
187
|
|
188
|
+
# Get the value for the provided operator, klass, key and value.
|
189
|
+
#
|
190
|
+
# This is necessary for special cases like $rename, $addToSet and $push.
|
191
|
+
#
|
192
|
+
# @param [ String ] operator The operator.
|
193
|
+
# @param [ Class ] klass The model class.
|
194
|
+
# @param [ String | Symbol ] key The field key.
|
195
|
+
# @param [ Object ] value The original value.
|
196
|
+
#
|
197
|
+
# @return [ Object ] Value prepared for the provided operator.
|
198
|
+
def value_for(operator, klass, key, value)
|
199
|
+
case operator
|
200
|
+
when "$rename" then value.to_s
|
201
|
+
when "$addToSet", "$push" then value.mongoize
|
202
|
+
else mongoize_for(operator, klass, operator, value)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
188
206
|
# Mongoize for the klass, key and value.
|
189
207
|
#
|
190
208
|
# @api private
|
@@ -140,6 +140,28 @@ module Mongoid
|
|
140
140
|
#
|
141
141
|
# @api private
|
142
142
|
def _mongoid_run_child_callbacks(kind, children: nil, &block)
|
143
|
+
if Mongoid::Config.around_callbacks_for_embeds
|
144
|
+
_mongoid_run_child_callbacks_with_around(kind, children: children, &block)
|
145
|
+
else
|
146
|
+
_mongoid_run_child_callbacks_without_around(kind, children: children, &block)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Execute the callbacks of given kind for embedded documents including
|
151
|
+
# around callbacks.
|
152
|
+
#
|
153
|
+
# @note This method is prone to stack overflow errors if the document
|
154
|
+
# has a large number of embedded documents. It is recommended to avoid
|
155
|
+
# using around callbacks for embedded documents until a proper solution
|
156
|
+
# is implemented.
|
157
|
+
#
|
158
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
159
|
+
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
160
|
+
# nil, callbacks will be executed on all cascadable children of
|
161
|
+
# the document.
|
162
|
+
#
|
163
|
+
# @api private
|
164
|
+
def _mongoid_run_child_callbacks_with_around(kind, children: nil, &block)
|
143
165
|
child, *tail = (children || cascadable_children(kind))
|
144
166
|
with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
|
145
167
|
if child.nil?
|
@@ -148,23 +170,91 @@ module Mongoid
|
|
148
170
|
child.run_callbacks(child_callback_type(kind, child), with_children: with_children, &block)
|
149
171
|
else
|
150
172
|
child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do
|
151
|
-
|
173
|
+
_mongoid_run_child_callbacks_with_around(kind, children: tail, &block)
|
152
174
|
end
|
153
175
|
end
|
154
176
|
end
|
155
177
|
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
178
|
+
# Execute the callbacks of given kind for embedded documents without
|
179
|
+
# around callbacks.
|
180
|
+
#
|
181
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
182
|
+
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
183
|
+
# nil, callbacks will be executed on all cascadable children of
|
184
|
+
# the document.
|
185
|
+
#
|
186
|
+
# @api private
|
187
|
+
def _mongoid_run_child_callbacks_without_around(kind, children: nil, &block)
|
188
|
+
children = (children || cascadable_children(kind))
|
189
|
+
callback_list = _mongoid_run_child_before_callbacks(kind, children: children)
|
190
|
+
return false if callback_list == false
|
191
|
+
value = block&.call
|
192
|
+
callback_list.each do |_next_sequence, env|
|
193
|
+
env.value &&= value
|
194
|
+
end
|
195
|
+
return false if _mongoid_run_child_after_callbacks(callback_list: callback_list) == false
|
196
|
+
|
197
|
+
value
|
198
|
+
end
|
199
|
+
|
200
|
+
# Execute the before callbacks of given kind for embedded documents.
|
201
|
+
#
|
202
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
203
|
+
# @param [ Array<Document> ] children Children to execute callbacks on.
|
204
|
+
# @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
|
205
|
+
# pairs of callback sequence and environment. This list will be later used
|
206
|
+
# to execute after callbacks in reverse order.
|
207
|
+
#
|
208
|
+
# @api private
|
209
|
+
def _mongoid_run_child_before_callbacks(kind, children: [], callback_list: [])
|
210
|
+
children.each do |child|
|
211
|
+
chain = child.__callbacks[child_callback_type(kind, child)]
|
212
|
+
env = ActiveSupport::Callbacks::Filters::Environment.new(child, false, nil)
|
213
|
+
next_sequence = compile_callbacks(chain)
|
214
|
+
unless next_sequence.final?
|
215
|
+
Mongoid.logger.warn("Around callbacks are disabled for embedded documents. Skipping around callbacks for #{child.class.name}.")
|
216
|
+
Mongoid.logger.warn("To enable around callbacks for embedded documents, set Mongoid::Config.around_callbacks_for_embeds to true.")
|
217
|
+
end
|
218
|
+
next_sequence.invoke_before(env)
|
219
|
+
return false if env.halted
|
220
|
+
env.value = !env.halted
|
221
|
+
callback_list << [next_sequence, env]
|
222
|
+
if (grandchildren = child.send(:cascadable_children, kind))
|
223
|
+
_mongoid_run_child_before_callbacks(kind, children: grandchildren, callback_list: callback_list)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
callback_list
|
227
|
+
end
|
228
|
+
|
229
|
+
# Execute the after callbacks.
|
230
|
+
#
|
231
|
+
# @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
|
232
|
+
# pairs of callback sequence and environment.
|
233
|
+
def _mongoid_run_child_after_callbacks(callback_list: [])
|
234
|
+
callback_list.reverse_each do |next_sequence, env|
|
235
|
+
next_sequence.invoke_after(env)
|
236
|
+
return false if env.halted
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns the stored callbacks to be executed later.
|
160
241
|
#
|
161
|
-
# @return [ Array<Symbol> ]
|
242
|
+
# @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
|
162
243
|
#
|
163
244
|
# @api private
|
164
245
|
def pending_callbacks
|
165
246
|
@pending_callbacks ||= [].to_set
|
166
247
|
end
|
167
248
|
|
249
|
+
# Stores callbacks to be executed later. A good use case for
|
250
|
+
# this is delaying the after_find and after_initialize callbacks until the
|
251
|
+
# associations are set on the document. This can also be used to delay
|
252
|
+
# applying the defaults on a document.
|
253
|
+
#
|
254
|
+
# @param [ Array<Symbol> ] value Method symbols of the pending callbacks to store.
|
255
|
+
#
|
256
|
+
# @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
|
257
|
+
#
|
168
258
|
# @api private
|
169
259
|
def pending_callbacks=(value)
|
170
260
|
@pending_callbacks = value
|
@@ -299,7 +389,7 @@ module Mongoid
|
|
299
389
|
end
|
300
390
|
self.class.send :define_method, name do
|
301
391
|
env = ActiveSupport::Callbacks::Filters::Environment.new(self, false, nil)
|
302
|
-
sequence = chain
|
392
|
+
sequence = compile_callbacks(chain)
|
303
393
|
sequence.invoke_before(env)
|
304
394
|
env.value = !env.halted
|
305
395
|
sequence.invoke_after(env)
|
@@ -309,5 +399,24 @@ module Mongoid
|
|
309
399
|
end
|
310
400
|
send(name)
|
311
401
|
end
|
402
|
+
|
403
|
+
# Compile the callback chain.
|
404
|
+
#
|
405
|
+
# This method hides the differences between ActiveSupport implementations
|
406
|
+
# before and after 7.1.
|
407
|
+
#
|
408
|
+
# @param [ ActiveSupport::Callbacks::CallbackChain ] chain The callback chain.
|
409
|
+
# @param [ Symbol | nil ] type The type of callback chain to compile.
|
410
|
+
#
|
411
|
+
# @return [ ActiveSupport::Callbacks::CallbackSequence ] The compiled callback sequence.
|
412
|
+
def compile_callbacks(chain, type = nil)
|
413
|
+
if chain.method(:compile).arity == 0
|
414
|
+
# ActiveSupport < 7.1
|
415
|
+
chain.compile
|
416
|
+
else
|
417
|
+
# ActiveSupport >= 7.1
|
418
|
+
chain.compile(type)
|
419
|
+
end
|
420
|
+
end
|
312
421
|
end
|
313
422
|
end
|
data/lib/mongoid/version.rb
CHANGED
@@ -557,6 +557,7 @@ describe 'callbacks integration tests' do
|
|
557
557
|
|
558
558
|
context 'nested embedded documents' do
|
559
559
|
config_override :prevent_multiple_calls_of_embedded_callbacks, true
|
560
|
+
config_override :around_callbacks_for_embeds, true
|
560
561
|
|
561
562
|
let(:logger) { Array.new }
|
562
563
|
|
@@ -581,4 +582,24 @@ describe 'callbacks integration tests' do
|
|
581
582
|
expect(logger).to eq(%i[embedded_twice embedded_once root])
|
582
583
|
end
|
583
584
|
end
|
585
|
+
|
586
|
+
context 'cascade callbacks' do
|
587
|
+
ruby_version_gte '3.0'
|
588
|
+
config_override :around_callbacks_for_embeds, false
|
589
|
+
|
590
|
+
let(:book) do
|
591
|
+
Book.new
|
592
|
+
end
|
593
|
+
|
594
|
+
before do
|
595
|
+
1500.times do
|
596
|
+
book.pages.build
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
# https://jira.mongodb.org/browse/MONGOID-5658
|
601
|
+
it 'does not raise SystemStackError' do
|
602
|
+
expect { book.save! }.not_to raise_error(SystemStackError)
|
603
|
+
end
|
604
|
+
end
|
584
605
|
end
|
@@ -2310,9 +2310,37 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
|
|
2310
2310
|
person.addresses.create!(street: "Bond St")
|
2311
2311
|
end
|
2312
2312
|
|
2313
|
+
let(:address) { person.addresses.first }
|
2314
|
+
|
2313
2315
|
it "returns true" do
|
2314
2316
|
expect(person.addresses.exists?).to be true
|
2315
2317
|
end
|
2318
|
+
|
2319
|
+
context 'when given specifying conditions' do
|
2320
|
+
context 'when the record exists in the association' do
|
2321
|
+
it 'returns true by condition' do
|
2322
|
+
expect(person.addresses.exists?(street: 'Bond St')).to be true
|
2323
|
+
end
|
2324
|
+
|
2325
|
+
it 'returns true by id' do
|
2326
|
+
expect(person.addresses.exists?(address._id)).to be true
|
2327
|
+
end
|
2328
|
+
|
2329
|
+
it 'returns false when given false' do
|
2330
|
+
expect(person.addresses.exists?(false)).to be false
|
2331
|
+
end
|
2332
|
+
|
2333
|
+
it 'returns false when given nil' do
|
2334
|
+
expect(person.addresses.exists?(nil)).to be false
|
2335
|
+
end
|
2336
|
+
end
|
2337
|
+
|
2338
|
+
context 'when the record does not exist in the association' do
|
2339
|
+
it 'returns false' do
|
2340
|
+
expect(person.addresses.exists?(street: 'Garfield Ave')).to be false
|
2341
|
+
end
|
2342
|
+
end
|
2343
|
+
end
|
2316
2344
|
end
|
2317
2345
|
|
2318
2346
|
context "when no documents exist in the database" do
|
@@ -2324,6 +2352,13 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
|
|
2324
2352
|
it "returns false" do
|
2325
2353
|
expect(person.addresses.exists?).to be false
|
2326
2354
|
end
|
2355
|
+
|
2356
|
+
context 'when given specifying conditions' do
|
2357
|
+
it 'returns false' do
|
2358
|
+
expect(person.addresses.exists?(street: 'Hyde Park Dr')).to be false
|
2359
|
+
expect(person.addresses.exists?(street: 'Garfield Ave')).to be false
|
2360
|
+
end
|
2361
|
+
end
|
2327
2362
|
end
|
2328
2363
|
end
|
2329
2364
|
|
@@ -2395,6 +2395,42 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
|
|
2395
2395
|
end
|
2396
2396
|
end
|
2397
2397
|
end
|
2398
|
+
|
2399
|
+
context 'when invoked with specifying conditions' do
|
2400
|
+
let(:other_person) { Person.create! }
|
2401
|
+
let(:post) { person.posts.first }
|
2402
|
+
|
2403
|
+
before do
|
2404
|
+
person.posts.create title: 'bumfuzzle'
|
2405
|
+
other_person.posts.create title: 'bumbershoot'
|
2406
|
+
end
|
2407
|
+
|
2408
|
+
context 'when the conditions match an associated record' do
|
2409
|
+
it 'detects its existence by condition' do
|
2410
|
+
expect(person.posts.exists?(title: 'bumfuzzle')).to be true
|
2411
|
+
expect(other_person.posts.exists?(title: 'bumbershoot')).to be true
|
2412
|
+
end
|
2413
|
+
|
2414
|
+
it 'detects its existence by id' do
|
2415
|
+
expect(person.posts.exists?(post._id)).to be true
|
2416
|
+
end
|
2417
|
+
|
2418
|
+
it 'returns false when given false' do
|
2419
|
+
expect(person.posts.exists?(false)).to be false
|
2420
|
+
end
|
2421
|
+
|
2422
|
+
it 'returns false when given nil' do
|
2423
|
+
expect(person.posts.exists?(nil)).to be false
|
2424
|
+
end
|
2425
|
+
end
|
2426
|
+
|
2427
|
+
context 'when the conditions match an unassociated record' do
|
2428
|
+
it 'does not detect its existence' do
|
2429
|
+
expect(person.posts.exists?(title: 'bumbershoot')).to be false
|
2430
|
+
expect(other_person.posts.exists?(title: 'bumfuzzle')).to be false
|
2431
|
+
end
|
2432
|
+
end
|
2433
|
+
end
|
2398
2434
|
end
|
2399
2435
|
|
2400
2436
|
context "when documents exist in application but not in database" do
|
@@ -2465,6 +2501,12 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
|
|
2465
2501
|
end
|
2466
2502
|
end
|
2467
2503
|
end
|
2504
|
+
|
2505
|
+
context 'when invoked with specifying conditions' do
|
2506
|
+
it 'returns false' do
|
2507
|
+
expect(person.posts.exists?(title: 'hullaballoo')).to be false
|
2508
|
+
end
|
2509
|
+
end
|
2468
2510
|
end
|
2469
2511
|
end
|
2470
2512
|
|
@@ -158,6 +158,16 @@ describe Mongoid::Contextual::Mongo do
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
end
|
161
|
+
|
162
|
+
context 'when for_js is present' do
|
163
|
+
let(:context) do
|
164
|
+
Band.for_js('this.name == "Depeche Mode"')
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'counts the expected records' do
|
168
|
+
expect(context.count).to eq(1)
|
169
|
+
end
|
170
|
+
end
|
161
171
|
end
|
162
172
|
|
163
173
|
describe "#estimated_count" do
|
@@ -3690,16 +3700,51 @@ describe Mongoid::Contextual::Mongo do
|
|
3690
3700
|
|
3691
3701
|
context "when the attributes are in the correct type" do
|
3692
3702
|
|
3693
|
-
|
3694
|
-
|
3703
|
+
context "when operation is $set" do
|
3704
|
+
|
3705
|
+
before do
|
3706
|
+
context.update_all("$set" => { name: "Smiths" })
|
3707
|
+
end
|
3708
|
+
|
3709
|
+
it "updates the first matching document" do
|
3710
|
+
expect(depeche_mode.reload.name).to eq("Smiths")
|
3711
|
+
end
|
3712
|
+
|
3713
|
+
it "updates the last matching document" do
|
3714
|
+
expect(new_order.reload.name).to eq("Smiths")
|
3715
|
+
end
|
3695
3716
|
end
|
3696
3717
|
|
3697
|
-
|
3698
|
-
|
3718
|
+
context "when operation is $push" do
|
3719
|
+
|
3720
|
+
before do
|
3721
|
+
depeche_mode.update_attribute(:genres, ["electronic"])
|
3722
|
+
new_order.update_attribute(:genres, ["electronic"])
|
3723
|
+
context.update_all("$push" => { genres: "pop" })
|
3724
|
+
end
|
3725
|
+
|
3726
|
+
it "updates the first matching document" do
|
3727
|
+
expect(depeche_mode.reload.genres).to eq(["electronic", "pop"])
|
3728
|
+
end
|
3729
|
+
|
3730
|
+
it "updates the last matching document" do
|
3731
|
+
expect(new_order.reload.genres).to eq(["electronic", "pop"])
|
3732
|
+
end
|
3699
3733
|
end
|
3700
3734
|
|
3701
|
-
|
3702
|
-
|
3735
|
+
context "when operation is $addToSet" do
|
3736
|
+
|
3737
|
+
before do
|
3738
|
+
context.update_all("$addToSet" => { genres: "electronic" })
|
3739
|
+
end
|
3740
|
+
|
3741
|
+
it "updates the first matching document" do
|
3742
|
+
expect(depeche_mode.reload.genres).to eq(["electronic"])
|
3743
|
+
end
|
3744
|
+
|
3745
|
+
it "updates the last matching document" do
|
3746
|
+
expect(new_order.reload.genres).to eq(["electronic"])
|
3747
|
+
end
|
3703
3748
|
end
|
3704
3749
|
end
|
3705
3750
|
|