mongoid 8.0.3 → 8.0.5
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/Rakefile +25 -0
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +17 -15
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +4 -0
- data/lib/mongoid/association/referenced/has_many/proxy.rb +4 -0
- data/lib/mongoid/atomic.rb +7 -0
- data/lib/mongoid/changeable.rb +1 -3
- data/lib/mongoid/criteria/queryable/extensions/array.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions/numeric.rb +0 -8
- data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -11
- data/lib/mongoid/criteria/queryable/extensions/symbol.rb +0 -10
- data/lib/mongoid/criteria/translator.rb +45 -0
- data/lib/mongoid/criteria.rb +1 -0
- data/lib/mongoid/document.rb +50 -13
- data/lib/mongoid/factory.rb +21 -8
- data/lib/mongoid/matcher.rb +21 -6
- data/lib/mongoid/reloadable.rb +3 -5
- data/lib/mongoid/shardable.rb +35 -11
- data/lib/mongoid/threaded.rb +30 -0
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +37 -32
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +143 -197
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +102 -114
- data/spec/mongoid/attributes_spec.rb +2 -2
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +0 -59
- data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
- data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -0
- data/spec/mongoid/criteria/translator_spec.rb +132 -0
- data/spec/mongoid/reloadable_spec.rb +24 -0
- data/spec/mongoid/shardable_models.rb +14 -0
- data/spec/mongoid/shardable_spec.rb +153 -61
- data/spec/mongoid_spec.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +656 -648
- 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: 53bba3a9611a89eaf77478beacbf4a8a3c6751503ecf1919407c7af05e134af0
|
4
|
+
data.tar.gz: ebe8a6705c4c035e99720d1a37e8103948aa1cb61a66ab42b0d426dd7e10c135
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15c3ecad78d34f2bdc3967042c0175b639d813aa44bcb2e6a5aa4ee5ec6d3adcb13e428accefb0edfa6b7dab59710829194e00cc17cb0f38ff5673957c97e6ce
|
7
|
+
data.tar.gz: ba5f2a0a8cd2ddc48650d9e7b67c162d4071f254ea9de03070308a411aeda8db2ac40c3a548d9543bed2bad637aa001e2a4ed0fe039cb380a30a69d6b79164fd
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/Rakefile
CHANGED
@@ -11,6 +11,15 @@ $: << File.join(ROOT, 'spec/shared/lib')
|
|
11
11
|
require "rake"
|
12
12
|
require "rspec/core/rake_task"
|
13
13
|
require 'mrss/spec_organizer'
|
14
|
+
require 'rubygems/package'
|
15
|
+
require 'rubygems/security/policies'
|
16
|
+
|
17
|
+
def signed_gem?(path_to_gem)
|
18
|
+
Gem::Package.new(path_to_gem, Gem::Security::HighSecurity).verify
|
19
|
+
true
|
20
|
+
rescue Gem::Security::Exception => e
|
21
|
+
false
|
22
|
+
end
|
14
23
|
|
15
24
|
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
16
25
|
require "mongoid/version"
|
@@ -103,3 +112,19 @@ namespace :release do
|
|
103
112
|
end
|
104
113
|
end
|
105
114
|
end
|
115
|
+
|
116
|
+
desc 'Verifies that all built gems in pkg/ are valid'
|
117
|
+
task :verify do
|
118
|
+
gems = Dir['pkg/*.gem']
|
119
|
+
if gems.empty?
|
120
|
+
puts 'There are no gems in pkg/ to verify'
|
121
|
+
else
|
122
|
+
gems.each do |gem|
|
123
|
+
if signed_gem?(gem)
|
124
|
+
puts "#{gem} is signed"
|
125
|
+
else
|
126
|
+
abort "#{gem} is not signed"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -154,6 +154,23 @@ module Mongoid
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
+
# Mongoid::Extensions::Array defines Array#delete_one, so we need
|
158
|
+
# to make sure that method behaves reasonably on proxies, too.
|
159
|
+
alias delete_one delete
|
160
|
+
|
161
|
+
# Removes a single document from the collection *in memory only*.
|
162
|
+
# It will *not* persist the change.
|
163
|
+
#
|
164
|
+
# @param [ Document ] document The document to delete.
|
165
|
+
#
|
166
|
+
# @api private
|
167
|
+
def _remove(document)
|
168
|
+
_target.delete_one(document)
|
169
|
+
_unscoped.delete_one(document)
|
170
|
+
update_attributes_hash
|
171
|
+
reindex
|
172
|
+
end
|
173
|
+
|
157
174
|
# Delete all the documents in the association without running callbacks.
|
158
175
|
#
|
159
176
|
# @example Delete all documents from the association.
|
@@ -397,21 +414,6 @@ module Mongoid
|
|
397
414
|
_association.criteria(_base, _target)
|
398
415
|
end
|
399
416
|
|
400
|
-
# Deletes one document from the target and unscoped.
|
401
|
-
#
|
402
|
-
# @api private
|
403
|
-
#
|
404
|
-
# @example Delete one document.
|
405
|
-
# relation.delete_one(doc)
|
406
|
-
#
|
407
|
-
# @param [ Document ] document The document to delete.
|
408
|
-
def delete_one(document)
|
409
|
-
_target.delete_one(document)
|
410
|
-
_unscoped.delete_one(document)
|
411
|
-
update_attributes_hash
|
412
|
-
reindex
|
413
|
-
end
|
414
|
-
|
415
417
|
# Integrate the document into the association. will set its metadata and
|
416
418
|
# attempt to bind the inverse.
|
417
419
|
#
|
@@ -137,6 +137,10 @@ module Mongoid
|
|
137
137
|
doc
|
138
138
|
end
|
139
139
|
|
140
|
+
# Mongoid::Extensions::Array defines Array#delete_one, so we need
|
141
|
+
# to make sure that method behaves reasonably on proxies, too.
|
142
|
+
alias delete_one delete
|
143
|
+
|
140
144
|
# Removes all associations between the base document and the target
|
141
145
|
# documents by deleting the foreign keys and the references, orphaning
|
142
146
|
# the target documents in the process.
|
@@ -105,6 +105,10 @@ module Mongoid
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
+
# Mongoid::Extensions::Array defines Array#delete_one, so we need
|
109
|
+
# to make sure that method behaves reasonably on proxies, too.
|
110
|
+
alias delete_one delete
|
111
|
+
|
108
112
|
# Deletes all related documents from the database given the supplied
|
109
113
|
# conditions.
|
110
114
|
#
|
data/lib/mongoid/atomic.rb
CHANGED
@@ -311,6 +311,13 @@ module Mongoid
|
|
311
311
|
|
312
312
|
private
|
313
313
|
|
314
|
+
# Clears all pending atomic updates.
|
315
|
+
def reset_atomic_updates!
|
316
|
+
Atomic::UPDATES.each do |update|
|
317
|
+
send(update).clear
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
314
321
|
# Generates the atomic updates in the correct order.
|
315
322
|
#
|
316
323
|
# @example Generate the updates.
|
data/lib/mongoid/changeable.rb
CHANGED
@@ -30,14 +30,6 @@ module Mongoid
|
|
30
30
|
::Time.at(self).utc
|
31
31
|
end
|
32
32
|
|
33
|
-
# Get the integer as a sort direction.
|
34
|
-
#
|
35
|
-
# @example Get the integer as a sort direction.
|
36
|
-
# 1.to_direction
|
37
|
-
#
|
38
|
-
# @return [ Integer ] self.
|
39
|
-
def to_direction; self; end
|
40
|
-
|
41
33
|
module ClassMethods
|
42
34
|
|
43
35
|
# Get the object as a numeric.
|
@@ -49,7 +49,7 @@ module Mongoid
|
|
49
49
|
split(/,/).inject({}) do |hash, spec|
|
50
50
|
hash.tap do |_hash|
|
51
51
|
field, direction = spec.strip.split(/\s/)
|
52
|
-
_hash[field.to_sym] =
|
52
|
+
_hash[field.to_sym] = Mongoid::Criteria::Translator.to_direction(direction)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -67,16 +67,6 @@ module Mongoid
|
|
67
67
|
::String.__expr_part__(self, value, negating)
|
68
68
|
end
|
69
69
|
|
70
|
-
# Get the string as a sort direction.
|
71
|
-
#
|
72
|
-
# @example Get the string as a sort direction.
|
73
|
-
# "1".to_direction
|
74
|
-
#
|
75
|
-
# @return [ Integer ] The direction.
|
76
|
-
def to_direction
|
77
|
-
self =~ /desc/i ? -1 : 1
|
78
|
-
end
|
79
|
-
|
80
70
|
module ClassMethods
|
81
71
|
|
82
72
|
# Get the value as a expression.
|
@@ -21,16 +21,6 @@ module Mongoid
|
|
21
21
|
::String.__expr_part__(self, value, negating)
|
22
22
|
end
|
23
23
|
|
24
|
-
# Get the symbol as a sort direction.
|
25
|
-
#
|
26
|
-
# @example Get the symbol as a sort direction.
|
27
|
-
# "1".to_direction
|
28
|
-
#
|
29
|
-
# @return [ Integer ] The direction.
|
30
|
-
def to_direction
|
31
|
-
to_s.to_direction
|
32
|
-
end
|
33
|
-
|
34
24
|
module ClassMethods
|
35
25
|
|
36
26
|
# Adds a method on symbol as a convenience for the MongoDB operator.
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
class Criteria
|
5
|
+
|
6
|
+
# This is a helper module for translating atomic and composite
|
7
|
+
# Ruby values into corresponding query and option components.
|
8
|
+
# Originally implemented as patches to core classes, that approach
|
9
|
+
# has generally fallen into disfavor, as it bleeds too much into
|
10
|
+
# the public namespace.
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
module Translator
|
14
|
+
extend self
|
15
|
+
|
16
|
+
# Converts the given value to a direction specification for use in
|
17
|
+
# sorting.
|
18
|
+
#
|
19
|
+
# @example Convert the value to a direction.
|
20
|
+
# Translator.to_direction(:desc)
|
21
|
+
# Translator.to_direction("1")
|
22
|
+
# Translator.to_direction(-1)
|
23
|
+
# Translator.to_direction(score: { "$meta": "textScore" })
|
24
|
+
#
|
25
|
+
# @param [ Hash | Numeric | String | Symbol ] value The value to convert.
|
26
|
+
#
|
27
|
+
# @return [ Hash | Numeric ] The direction.
|
28
|
+
def to_direction(value)
|
29
|
+
case value
|
30
|
+
when Hash then
|
31
|
+
value
|
32
|
+
when Numeric then
|
33
|
+
value
|
34
|
+
when String then
|
35
|
+
value =~ /desc/i ? -1 : 1
|
36
|
+
when Symbol then
|
37
|
+
to_direction(value.to_s)
|
38
|
+
else
|
39
|
+
raise ArgumentError, "cannot translate #{value.inspect} (#{value.class}) to a direction specification"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/mongoid/criteria.rb
CHANGED
data/lib/mongoid/document.rb
CHANGED
@@ -101,7 +101,7 @@ module Mongoid
|
|
101
101
|
#
|
102
102
|
# @return [ Document ] A new document.
|
103
103
|
def initialize(attrs = nil, &block)
|
104
|
-
construct_document(attrs,
|
104
|
+
construct_document(attrs, &block)
|
105
105
|
end
|
106
106
|
|
107
107
|
# Return the model name of the document.
|
@@ -208,13 +208,22 @@ module Mongoid
|
|
208
208
|
# Does the construction of a document.
|
209
209
|
#
|
210
210
|
# @param [ Hash ] attrs The attributes to set up the document with.
|
211
|
-
# @param [
|
212
|
-
#
|
211
|
+
# @param [ Hash ] options The options to use.
|
212
|
+
#
|
213
|
+
# @option options [ true | false ] :execute_callbacks Flag specifies
|
214
|
+
# whether callbacks should be run.
|
213
215
|
#
|
214
216
|
# @return [ Document ] A new document.
|
215
217
|
#
|
218
|
+
# @note A Ruby 2.x bug prevents the options hash from being keyword
|
219
|
+
# arguments. Once we drop support for Ruby 2.x, we can reimplement
|
220
|
+
# the options hash as keyword arguments.
|
221
|
+
# See https://bugs.ruby-lang.org/issues/15753
|
222
|
+
#
|
216
223
|
# @api private
|
217
|
-
def construct_document(attrs = nil,
|
224
|
+
def construct_document(attrs = nil, options = {})
|
225
|
+
execute_callbacks = options.fetch(:execute_callbacks, Threaded.execute_callbacks?)
|
226
|
+
|
218
227
|
@__parent = nil
|
219
228
|
_building do
|
220
229
|
@new_record = true
|
@@ -281,6 +290,20 @@ module Mongoid
|
|
281
290
|
|
282
291
|
module ClassMethods
|
283
292
|
|
293
|
+
# Indicate whether callbacks should be invoked by default or not,
|
294
|
+
# within the block. Callbacks may always be explicitly invoked by passing
|
295
|
+
# `execute_callbacks: true` where available.
|
296
|
+
#
|
297
|
+
# @params execute_callbacks [ true | false ] Whether callbacks should be
|
298
|
+
# suppressed or not.
|
299
|
+
def with_callbacks(execute_callbacks)
|
300
|
+
saved, Threaded.execute_callbacks =
|
301
|
+
Threaded.execute_callbacks?, execute_callbacks
|
302
|
+
yield
|
303
|
+
ensure
|
304
|
+
Threaded.execute_callbacks = saved
|
305
|
+
end
|
306
|
+
|
284
307
|
# Instantiate a new object, only when loaded from the database or when
|
285
308
|
# the attributes have already been typecast.
|
286
309
|
#
|
@@ -295,7 +318,7 @@ module Mongoid
|
|
295
318
|
#
|
296
319
|
# @return [ Document ] A new document.
|
297
320
|
def instantiate(attrs = nil, selected_fields = nil, &block)
|
298
|
-
instantiate_document(attrs, selected_fields,
|
321
|
+
instantiate_document(attrs, selected_fields, &block)
|
299
322
|
end
|
300
323
|
|
301
324
|
# Instantiate the document.
|
@@ -303,13 +326,20 @@ module Mongoid
|
|
303
326
|
# @param [ Hash ] attrs The hash of attributes to instantiate with.
|
304
327
|
# @param [ Integer ] selected_fields The selected fields from the
|
305
328
|
# criteria.
|
306
|
-
# @param [
|
307
|
-
#
|
329
|
+
# @param [ Hash ] options The options to use.
|
330
|
+
#
|
331
|
+
# @option options [ true | false ] :execute_callbacks Flag specifies
|
332
|
+
# whether callbacks should be run.
|
308
333
|
#
|
309
334
|
# @return [ Document ] A new document.
|
310
335
|
#
|
336
|
+
# @note A Ruby 2.x bug prevents the options hash from being keyword
|
337
|
+
# arguments. Once we drop support for Ruby 2.x, we can reimplement
|
338
|
+
# the options hash as keyword arguments.
|
339
|
+
#
|
311
340
|
# @api private
|
312
|
-
def instantiate_document(attrs = nil, selected_fields = nil,
|
341
|
+
def instantiate_document(attrs = nil, selected_fields = nil, options = {})
|
342
|
+
execute_callbacks = options.fetch(:execute_callbacks, Threaded.execute_callbacks?)
|
313
343
|
attributes = if Mongoid.legacy_attributes
|
314
344
|
attrs
|
315
345
|
else
|
@@ -340,15 +370,22 @@ module Mongoid
|
|
340
370
|
# Allocates and constructs a document.
|
341
371
|
#
|
342
372
|
# @param [ Hash ] attrs The attributes to set up the document with.
|
343
|
-
# @param [
|
344
|
-
#
|
373
|
+
# @param [ Hash ] options The options to use.
|
374
|
+
#
|
375
|
+
# @option options [ true | false ] :execute_callbacks Flag specifies
|
376
|
+
# whether callbacks should be run.
|
377
|
+
#
|
378
|
+
# @note A Ruby 2.x bug prevents the options hash from being keyword
|
379
|
+
# arguments. Once we drop support for Ruby 2.x, we can reimplement
|
380
|
+
# the options hash as keyword arguments.
|
381
|
+
# See https://bugs.ruby-lang.org/issues/15753
|
345
382
|
#
|
346
383
|
# @return [ Document ] A new document.
|
347
384
|
#
|
348
385
|
# @api private
|
349
|
-
def construct_document(attrs = nil,
|
350
|
-
|
351
|
-
|
386
|
+
def construct_document(attrs = nil, options = {})
|
387
|
+
execute_callbacks = options.fetch(:execute_callbacks, Threaded.execute_callbacks?)
|
388
|
+
with_callbacks(execute_callbacks) { new(attrs) }
|
352
389
|
end
|
353
390
|
|
354
391
|
# Returns all types to query for when using this class as the base.
|
data/lib/mongoid/factory.rb
CHANGED
@@ -25,27 +25,40 @@ module Mongoid
|
|
25
25
|
#
|
26
26
|
# @return [ Document ] The instantiated document.
|
27
27
|
def build(klass, attributes = nil)
|
28
|
-
|
28
|
+
# A bug in Ruby 2.x (including 2.7.7) causes the attributes hash to be
|
29
|
+
# interpreted as keyword arguments, because execute_build accepts
|
30
|
+
# a keyword argument. Forcing an empty set of keyword arguments works
|
31
|
+
# around the bug. Once Ruby 2.x support is dropped, this hack can be
|
32
|
+
# removed.
|
33
|
+
# See https://bugs.ruby-lang.org/issues/15753
|
34
|
+
execute_build(klass, attributes)
|
29
35
|
end
|
30
36
|
|
31
37
|
# Execute the build.
|
32
38
|
#
|
33
39
|
# @param [ Class ] klass The class to instantiate from if _type is not present.
|
34
40
|
# @param [ Hash ] attributes The document attributes.
|
35
|
-
# @param [
|
36
|
-
#
|
41
|
+
# @param [ Hash ] options The options to use.
|
42
|
+
#
|
43
|
+
# @option options [ true | false ] :execute_callbacks Flag specifies
|
44
|
+
# whether callbacks should be run.
|
45
|
+
#
|
46
|
+
# @note A Ruby 2.x bug prevents the options hash from being keyword
|
47
|
+
# arguments. Once we drop support for Ruby 2.x, we can reimplement
|
48
|
+
# the options hash as keyword arguments.
|
49
|
+
# See https://bugs.ruby-lang.org/issues/15753
|
37
50
|
#
|
38
51
|
# @return [ Document ] The instantiated document.
|
39
52
|
#
|
40
53
|
# @api private
|
41
|
-
def execute_build(klass, attributes = nil,
|
54
|
+
def execute_build(klass, attributes = nil, options = {})
|
42
55
|
attributes ||= {}
|
43
56
|
dvalue = attributes[klass.discriminator_key] || attributes[klass.discriminator_key.to_sym]
|
44
57
|
type = klass.get_discriminator_mapping(dvalue)
|
45
58
|
if type
|
46
|
-
type.construct_document(attributes,
|
59
|
+
type.construct_document(attributes, options)
|
47
60
|
else
|
48
|
-
klass.construct_document(attributes,
|
61
|
+
klass.construct_document(attributes, options)
|
49
62
|
end
|
50
63
|
end
|
51
64
|
|
@@ -76,7 +89,7 @@ module Mongoid
|
|
76
89
|
#
|
77
90
|
# @return [ Document ] The instantiated document.
|
78
91
|
def from_db(klass, attributes = nil, criteria = nil, selected_fields = nil)
|
79
|
-
execute_from_db(klass, attributes, criteria, selected_fields
|
92
|
+
execute_from_db(klass, attributes, criteria, selected_fields)
|
80
93
|
end
|
81
94
|
|
82
95
|
# Execute from_db.
|
@@ -97,7 +110,7 @@ module Mongoid
|
|
97
110
|
# @return [ Document ] The instantiated document.
|
98
111
|
#
|
99
112
|
# @api private
|
100
|
-
def execute_from_db(klass, attributes = nil, criteria = nil, selected_fields = nil, execute_callbacks:
|
113
|
+
def execute_from_db(klass, attributes = nil, criteria = nil, selected_fields = nil, execute_callbacks: Threaded.execute_callbacks?)
|
101
114
|
if criteria
|
102
115
|
selected_fields ||= criteria.options[:fields]
|
103
116
|
end
|
data/lib/mongoid/matcher.rb
CHANGED
@@ -2,7 +2,6 @@ module Mongoid
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
module Matcher
|
5
|
-
|
6
5
|
# Extracts field values in the document at the specified key.
|
7
6
|
#
|
8
7
|
# The document can be a Hash or a model instance.
|
@@ -45,7 +44,7 @@ module Mongoid
|
|
45
44
|
# If a document has hash fields, as_attributes would keep those fields
|
46
45
|
# as Hash instances which do not offer indifferent access.
|
47
46
|
# Convert to BSON::Document to get indifferent access on hash fields.
|
48
|
-
document =
|
47
|
+
document = document.send(:as_attributes)
|
49
48
|
end
|
50
49
|
|
51
50
|
current = [document]
|
@@ -55,8 +54,9 @@ module Mongoid
|
|
55
54
|
current.each do |doc|
|
56
55
|
case doc
|
57
56
|
when Hash
|
58
|
-
|
59
|
-
|
57
|
+
actual_key = find_exact_key(doc, field)
|
58
|
+
if !actual_key.nil?
|
59
|
+
new << doc[actual_key]
|
60
60
|
end
|
61
61
|
when Array
|
62
62
|
if (index = field.to_i).to_s == field
|
@@ -66,8 +66,9 @@ module Mongoid
|
|
66
66
|
end
|
67
67
|
doc.each do |subdoc|
|
68
68
|
if Hash === subdoc
|
69
|
-
|
70
|
-
|
69
|
+
actual_key = find_exact_key(subdoc, field)
|
70
|
+
if !actual_key.nil?
|
71
|
+
new << subdoc[actual_key]
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
@@ -79,6 +80,20 @@ module Mongoid
|
|
79
80
|
|
80
81
|
current
|
81
82
|
end
|
83
|
+
|
84
|
+
# Indifferent string or symbol key lookup, returning the exact key.
|
85
|
+
#
|
86
|
+
# @param [ Hash ] hash The input hash.
|
87
|
+
# @param [ String | Symbol ] key The key to perform indifferent lookups with.
|
88
|
+
#
|
89
|
+
# @return [ String | Symbol | nil ] The exact key (with the correct type) that exists in the hash, or nil if the key does not exist.
|
90
|
+
module_function def find_exact_key(hash, key)
|
91
|
+
key_s = key.to_s
|
92
|
+
return key_s if hash.key?(key_s)
|
93
|
+
|
94
|
+
key_sym = key.to_sym
|
95
|
+
hash.key?(key_sym) ? key_sym : nil
|
96
|
+
end
|
82
97
|
end
|
83
98
|
end
|
84
99
|
|
data/lib/mongoid/reloadable.rb
CHANGED
@@ -16,16 +16,14 @@ module Mongoid
|
|
16
16
|
#
|
17
17
|
# @return [ Document ] The document, reloaded.
|
18
18
|
def reload
|
19
|
-
if @atomic_selector
|
20
|
-
# Clear atomic_selector cache for sharded clusters. MONGOID-5076
|
21
|
-
remove_instance_variable('@atomic_selector')
|
22
|
-
end
|
23
|
-
|
24
19
|
reloaded = _reload
|
25
20
|
if Mongoid.raise_not_found_error && (reloaded.nil? || reloaded.empty?)
|
26
21
|
shard_keys = atomic_selector.with_indifferent_access.slice(*shard_key_fields, :_id)
|
27
22
|
raise Errors::DocumentNotFound.new(self.class, _id, shard_keys)
|
28
23
|
end
|
24
|
+
|
25
|
+
reset_atomic_updates!
|
26
|
+
|
29
27
|
@attributes = reloaded
|
30
28
|
@attributes_before_type_cast = @attributes.dup
|
31
29
|
@changed_attributes = {}
|
data/lib/mongoid/shardable.rb
CHANGED
@@ -47,18 +47,22 @@ module Mongoid
|
|
47
47
|
self.class.shard_key_fields
|
48
48
|
end
|
49
49
|
|
50
|
-
# Returns the selector that would match the
|
51
|
-
#
|
50
|
+
# Returns the selector that would match the defined shard keys. If
|
51
|
+
# `prefer_persisted` is false (the default), it uses the current values
|
52
|
+
# of the specified shard keys, otherwise, it will try to use whatever value
|
53
|
+
# was most recently persisted.
|
54
|
+
#
|
55
|
+
# @param [ true | false ] prefer_persisted Whether to use the current
|
56
|
+
# value of the shard key fields, or to use their most recently persisted
|
57
|
+
# values.
|
52
58
|
#
|
53
59
|
# @return [ Hash ] The shard key selector.
|
54
60
|
#
|
55
61
|
# @api private
|
56
|
-
def shard_key_selector
|
57
|
-
|
58
|
-
|
59
|
-
selector[field.to_s] = send(field)
|
62
|
+
def shard_key_selector(prefer_persisted: false)
|
63
|
+
shard_key_fields.each_with_object({}) do |field, selector|
|
64
|
+
selector[field.to_s] = shard_key_field_value(field.to_s, prefer_persisted: prefer_persisted)
|
60
65
|
end
|
61
|
-
selector
|
62
66
|
end
|
63
67
|
|
64
68
|
# Returns the selector that would match the existing version of this
|
@@ -72,11 +76,31 @@ module Mongoid
|
|
72
76
|
#
|
73
77
|
# @api private
|
74
78
|
def shard_key_selector_in_db
|
75
|
-
|
76
|
-
|
77
|
-
|
79
|
+
shard_key_selector(prefer_persisted: true)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the value for the named shard key. If the field identifies
|
83
|
+
# an embedded document, the key will be parsed and recursively evaluated.
|
84
|
+
# If `prefer_persisted` is true, the value last persisted to the database
|
85
|
+
# will be returned, regardless of what the current value of the attribute
|
86
|
+
# may be.
|
87
|
+
#
|
88
|
+
# @param [String] field The name of the field to evaluate
|
89
|
+
# @param [ true|false ] prefer_persisted Whether or not to prefer the
|
90
|
+
# persisted value over the current value.
|
91
|
+
#
|
92
|
+
# @return [ Object ] The value of the named field.
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
def shard_key_field_value(field, prefer_persisted:)
|
96
|
+
if field.include?(".")
|
97
|
+
relation, remaining = field.split(".", 2)
|
98
|
+
send(relation)&.shard_key_field_value(remaining, prefer_persisted: prefer_persisted)
|
99
|
+
elsif prefer_persisted && !new_record?
|
100
|
+
attribute_was(field)
|
101
|
+
else
|
102
|
+
send(field)
|
78
103
|
end
|
79
|
-
selector
|
80
104
|
end
|
81
105
|
|
82
106
|
module ClassMethods
|
data/lib/mongoid/threaded.rb
CHANGED
@@ -26,6 +26,10 @@ module Mongoid
|
|
26
26
|
hash[key] = "[mongoid]:#{key}-stack"
|
27
27
|
end
|
28
28
|
|
29
|
+
# The key storing the default value for whether or not callbacks are
|
30
|
+
# executed on documents.
|
31
|
+
EXECUTE_CALLBACKS = '[mongoid]:execute-callbacks'
|
32
|
+
|
29
33
|
extend self
|
30
34
|
|
31
35
|
# Begin entry into a named thread local stack.
|
@@ -346,5 +350,31 @@ module Mongoid
|
|
346
350
|
session.end_session if session
|
347
351
|
Thread.current["[mongoid]:session"] = nil
|
348
352
|
end
|
353
|
+
|
354
|
+
# Queries whether document callbacks should be executed by default for the
|
355
|
+
# current thread.
|
356
|
+
#
|
357
|
+
# Unless otherwise indicated (by #execute_callbacks=), this will return
|
358
|
+
# true.
|
359
|
+
#
|
360
|
+
# @return [ true | false ] Whether or not document callbacks should be
|
361
|
+
# executed by default.
|
362
|
+
def execute_callbacks?
|
363
|
+
if Thread.current.key?(EXECUTE_CALLBACKS)
|
364
|
+
Thread.current[EXECUTE_CALLBACKS]
|
365
|
+
else
|
366
|
+
true
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Indicates whether document callbacks should be invoked by default for
|
371
|
+
# the current thread. Individual documents may further override the
|
372
|
+
# callback behavior, but this will be used for the default behavior.
|
373
|
+
#
|
374
|
+
# @param flag [ true | false ] Whether or not document callbacks should be
|
375
|
+
# executed by default.
|
376
|
+
def execute_callbacks=(flag)
|
377
|
+
Thread.current[EXECUTE_CALLBACKS] = flag
|
378
|
+
end
|
349
379
|
end
|
350
380
|
end
|
data/lib/mongoid/traversable.rb
CHANGED
data/lib/mongoid/version.rb
CHANGED