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
@@ -140,32 +140,6 @@ 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,
|
145
|
-
children: children,
|
146
|
-
&block)
|
147
|
-
else
|
148
|
-
_mongoid_run_child_callbacks_without_around(kind,
|
149
|
-
children: children,
|
150
|
-
&block)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# Execute the callbacks of given kind for embedded documents including
|
155
|
-
# around callbacks.
|
156
|
-
#
|
157
|
-
# @note This method is prone to stack overflow errors if the document
|
158
|
-
# has a large number of embedded documents. It is recommended to avoid
|
159
|
-
# using around callbacks for embedded documents until a proper solution
|
160
|
-
# is implemented.
|
161
|
-
#
|
162
|
-
# @param [ Symbol ] kind The type of callback to execute.
|
163
|
-
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
164
|
-
# nil, callbacks will be executed on all cascadable children of
|
165
|
-
# the document.
|
166
|
-
#
|
167
|
-
# @api private
|
168
|
-
def _mongoid_run_child_callbacks_with_around(kind, children: nil, &block)
|
169
143
|
child, *tail = (children || cascadable_children(kind))
|
170
144
|
with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
|
171
145
|
if child.nil?
|
@@ -179,83 +153,18 @@ module Mongoid
|
|
179
153
|
end
|
180
154
|
end
|
181
155
|
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
187
|
-
# nil, callbacks will be executed on all cascadable children of
|
188
|
-
# the document.
|
189
|
-
#
|
190
|
-
# @api private
|
191
|
-
def _mongoid_run_child_callbacks_without_around(kind, children: nil, &block)
|
192
|
-
children = (children || cascadable_children(kind))
|
193
|
-
callback_list = _mongoid_run_child_before_callbacks(kind, children: children)
|
194
|
-
return false if callback_list == false
|
195
|
-
value = block&.call
|
196
|
-
callback_list.each do |_next_sequence, env|
|
197
|
-
env.value &&= value
|
198
|
-
end
|
199
|
-
return false if _mongoid_run_child_after_callbacks(callback_list: callback_list) == false
|
200
|
-
|
201
|
-
value
|
202
|
-
end
|
203
|
-
|
204
|
-
# Execute the before callbacks of given kind for embedded documents.
|
205
|
-
#
|
206
|
-
# @param [ Symbol ] kind The type of callback to execute.
|
207
|
-
# @param [ Array<Document> ] children Children to execute callbacks on.
|
208
|
-
# @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
|
209
|
-
# pairs of callback sequence and environment. This list will be later used
|
210
|
-
# to execute after callbacks in reverse order.
|
211
|
-
#
|
212
|
-
# @api private
|
213
|
-
def _mongoid_run_child_before_callbacks(kind, children: [], callback_list: [])
|
214
|
-
children.each do |child|
|
215
|
-
chain = child.__callbacks[child_callback_type(kind, child)]
|
216
|
-
env = ActiveSupport::Callbacks::Filters::Environment.new(child, false, nil)
|
217
|
-
next_sequence = compile_callbacks(chain)
|
218
|
-
unless next_sequence.final?
|
219
|
-
Mongoid.logger.warn("Around callbacks are disabled for embedded documents. Skipping around callbacks for #{child.class.name}.")
|
220
|
-
Mongoid.logger.warn("To enable around callbacks for embedded documents, set Mongoid::Config.around_callbacks_for_embeds to true.")
|
221
|
-
end
|
222
|
-
next_sequence.invoke_before(env)
|
223
|
-
return false if env.halted
|
224
|
-
env.value = !env.halted
|
225
|
-
callback_list << [next_sequence, env]
|
226
|
-
end
|
227
|
-
callback_list
|
228
|
-
end
|
229
|
-
|
230
|
-
# Execute the after callbacks.
|
231
|
-
#
|
232
|
-
# @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
|
233
|
-
# pairs of callback sequence and environment.
|
234
|
-
def _mongoid_run_child_after_callbacks(callback_list: [])
|
235
|
-
callback_list.reverse_each do |next_sequence, env|
|
236
|
-
next_sequence.invoke_after(env)
|
237
|
-
return false if env.halted
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
# Returns the stored callbacks to be executed later.
|
156
|
+
# This is used to store callbacks to be executed later. A good use case for
|
157
|
+
# this is delaying the after_find and after_initialize callbacks until the
|
158
|
+
# associations are set on the document. This can also be used to delay
|
159
|
+
# applying the defaults on a document.
|
242
160
|
#
|
243
|
-
# @return [ Array<Symbol> ]
|
161
|
+
# @return [ Array<Symbol> ] an array of symbols that represent the pending callbacks.
|
244
162
|
#
|
245
163
|
# @api private
|
246
164
|
def pending_callbacks
|
247
165
|
@pending_callbacks ||= [].to_set
|
248
166
|
end
|
249
167
|
|
250
|
-
# Stores callbacks to be executed later. A good use case for
|
251
|
-
# this is delaying the after_find and after_initialize callbacks until the
|
252
|
-
# associations are set on the document. This can also be used to delay
|
253
|
-
# applying the defaults on a document.
|
254
|
-
#
|
255
|
-
# @param [ Array<Symbol> ] value Method symbols of the pending callbacks to store.
|
256
|
-
#
|
257
|
-
# @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
|
258
|
-
#
|
259
168
|
# @api private
|
260
169
|
def pending_callbacks=(value)
|
261
170
|
@pending_callbacks = value
|
@@ -390,7 +299,7 @@ module Mongoid
|
|
390
299
|
end
|
391
300
|
self.class.send :define_method, name do
|
392
301
|
env = ActiveSupport::Callbacks::Filters::Environment.new(self, false, nil)
|
393
|
-
sequence =
|
302
|
+
sequence = chain.compile
|
394
303
|
sequence.invoke_before(env)
|
395
304
|
env.value = !env.halted
|
396
305
|
sequence.invoke_after(env)
|
@@ -400,24 +309,5 @@ module Mongoid
|
|
400
309
|
end
|
401
310
|
send(name)
|
402
311
|
end
|
403
|
-
|
404
|
-
# Compile the callback chain.
|
405
|
-
#
|
406
|
-
# This method hides the differences between ActiveSupport implementations
|
407
|
-
# before and after 7.1.
|
408
|
-
#
|
409
|
-
# @param [ ActiveSupport::Callbacks::CallbackChain ] chain The callback chain.
|
410
|
-
# @param [ Symbol | nil ] type The type of callback chain to compile.
|
411
|
-
#
|
412
|
-
# @return [ ActiveSupport::Callbacks::CallbackSequence ] The compiled callback sequence.
|
413
|
-
def compile_callbacks(chain, type = nil)
|
414
|
-
if chain.method(:compile).arity == 0
|
415
|
-
# ActiveSupport < 7.1
|
416
|
-
chain.compile
|
417
|
-
else
|
418
|
-
# ActiveSupport >= 7.1
|
419
|
-
chain.compile(type)
|
420
|
-
end
|
421
|
-
end
|
422
312
|
end
|
423
313
|
end
|
@@ -46,7 +46,7 @@ module Mongoid
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
# Per https://
|
49
|
+
# Per https://www.mongodb.com/docs/ruby-driver/current/tutorials/bson-v4/#time-instances,
|
50
50
|
# > Times in BSON (and MongoDB) can only have millisecond precision. When Ruby Time instances
|
51
51
|
# are serialized to BSON or Extended JSON, the times are floored to the nearest millisecond.
|
52
52
|
#
|
data/lib/mongoid/matcher/type.rb
CHANGED
@@ -100,6 +100,7 @@ module Mongoid
|
|
100
100
|
#
|
101
101
|
# @return [ Document ] The document.
|
102
102
|
def prepare_insert(options = {})
|
103
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
103
104
|
return self if performing_validations?(options) &&
|
104
105
|
invalid?(options[:context] || :create)
|
105
106
|
run_callbacks(:save, with_children: false) do
|
@@ -16,7 +16,6 @@ module Mongoid
|
|
16
16
|
#
|
17
17
|
# @return [ TrueClass ] True.
|
18
18
|
def delete(options = {})
|
19
|
-
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
20
19
|
prepare_delete do
|
21
20
|
unless options[:persist] == false
|
22
21
|
if embedded?
|
@@ -102,6 +101,7 @@ module Mongoid
|
|
102
101
|
#
|
103
102
|
# @return [ Object ] The result of the block.
|
104
103
|
def prepare_delete
|
104
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
105
105
|
yield(self)
|
106
106
|
freeze
|
107
107
|
self.destroyed = true
|
@@ -14,7 +14,13 @@ module Mongoid
|
|
14
14
|
#
|
15
15
|
# @param [ Hash ] options Options to pass to the save.
|
16
16
|
#
|
17
|
-
# @
|
17
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
18
|
+
# attribute will be updated with the current time. When this option is
|
19
|
+
# false, none of the embedded documents will be touched. This option is
|
20
|
+
# ignored when saving a new document, and the created_at and updated_at
|
21
|
+
# will be set to the current time.
|
22
|
+
#
|
23
|
+
# @return [ true | false ] True if success, false if not.
|
18
24
|
def save(options = {})
|
19
25
|
if new_record?
|
20
26
|
!insert(options).new_record?
|
@@ -31,6 +37,12 @@ module Mongoid
|
|
31
37
|
#
|
32
38
|
# @param [ Hash ] options Options to pass to the save.
|
33
39
|
#
|
40
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
41
|
+
# attribute will be updated with the current time. When this option is
|
42
|
+
# false, none of the embedded documents will be touched.This option is
|
43
|
+
# ignored when saving a new document, and the created_at and updated_at
|
44
|
+
# will be set to the current time.
|
45
|
+
#
|
34
46
|
# @raise [ Errors::Validations ] If validation failed.
|
35
47
|
# @raise [ Errors::Callback ] If a callback returns false.
|
36
48
|
#
|
@@ -13,8 +13,8 @@ module Mongoid
|
|
13
13
|
# @example Unset the values.
|
14
14
|
# document.unset(:first_name, :last_name, :middle)
|
15
15
|
#
|
16
|
-
# @param [ Array<String | Symbol> ] fields
|
17
|
-
# unset.
|
16
|
+
# @param [ [ String | Symbol | Array<String | Symbol>]... ] *fields
|
17
|
+
# The names of the field(s) to unset.
|
18
18
|
#
|
19
19
|
# @return [ Document ] The document.
|
20
20
|
def unset(*fields)
|
@@ -91,16 +91,23 @@ module Mongoid
|
|
91
91
|
#
|
92
92
|
# @param [ Hash ] options The options.
|
93
93
|
#
|
94
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
95
|
+
# attribute will be updated with the current time.
|
96
|
+
#
|
94
97
|
# @return [ true | false ] The result of the update.
|
95
98
|
def prepare_update(options = {})
|
99
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
100
|
+
enforce_immutability_of_id_field!
|
96
101
|
return false if performing_validations?(options) &&
|
97
102
|
invalid?(options[:context] || :update)
|
98
103
|
process_flagged_destroys
|
104
|
+
update_children = cascadable_children(:update)
|
105
|
+
process_touch_option(options, update_children)
|
99
106
|
run_callbacks(:save, with_children: false) do
|
100
107
|
run_callbacks(:update, with_children: false) do
|
101
108
|
run_callbacks(:persist_parent, with_children: false) do
|
102
109
|
_mongoid_run_child_callbacks(:save) do
|
103
|
-
_mongoid_run_child_callbacks(:update) do
|
110
|
+
_mongoid_run_child_callbacks(:update, children: update_children) do
|
104
111
|
result = yield(self)
|
105
112
|
self.previously_new_record = false
|
106
113
|
post_process_persist(result, options)
|
@@ -160,6 +167,49 @@ module Mongoid
|
|
160
167
|
end
|
161
168
|
end
|
162
169
|
end
|
170
|
+
|
171
|
+
# If there is a touch option and it is false, this method will call the
|
172
|
+
# timeless method so that the updated_at attribute is not updated. It
|
173
|
+
# will call the timeless method on all of the cascadable children as
|
174
|
+
# well. Note that timeless is cleared in the before_update callback.
|
175
|
+
#
|
176
|
+
# @param [ Hash ] options The options.
|
177
|
+
# @param [ Array<Document> ] children The children that the :update
|
178
|
+
# callbacks will be executed on.
|
179
|
+
#
|
180
|
+
# @option options [ true | false ] :touch Whether or not the updated_at
|
181
|
+
# attribute will be updated with the current time.
|
182
|
+
def process_touch_option(options, children)
|
183
|
+
unless options.fetch(:touch, true)
|
184
|
+
timeless
|
185
|
+
children.each(&:timeless)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Checks to see if the _id field has been modified. If it has, and if
|
190
|
+
# the document has already been persisted, this is an error. Otherwise,
|
191
|
+
# returns without side-effects.
|
192
|
+
#
|
193
|
+
# Note that if `Mongoid::Config.immutable_ids` is false, this will do
|
194
|
+
# nothing.
|
195
|
+
#
|
196
|
+
# @raise [ Errors::ImmutableAttribute ] if _id has changed, and document
|
197
|
+
# has been persisted.
|
198
|
+
def enforce_immutability_of_id_field!
|
199
|
+
# special case here: we *do* allow the _id to be mutated if it was
|
200
|
+
# previously nil. This addresses an odd case exposed in
|
201
|
+
# has_one/proxy_spec.rb where `person.create_address` would
|
202
|
+
# (somehow?) create the address with a nil _id first, before then
|
203
|
+
# saving it *again* with the correct _id.
|
204
|
+
|
205
|
+
if _id_changed? && !_id_was.nil? && persisted?
|
206
|
+
if Mongoid::Config.immutable_ids
|
207
|
+
raise Errors::ImmutableAttribute.new(:_id, _id)
|
208
|
+
else
|
209
|
+
Mongoid::Warnings.warn_mutable_ids
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
163
213
|
end
|
164
214
|
end
|
165
215
|
end
|
@@ -10,16 +10,32 @@ module Mongoid
|
|
10
10
|
# database, then Mongo will insert a new one, otherwise the fields will get
|
11
11
|
# overwritten with new values on the existing document.
|
12
12
|
#
|
13
|
+
# If the replace option is true, unspecified attributes will be dropped,
|
14
|
+
# and if it is false, unspecified attributes will be maintained. The
|
15
|
+
# replace option defaults to true in Mongoid 8.1 and earlier. The default
|
16
|
+
# will be flipped to false in Mongoid 9.
|
17
|
+
#
|
13
18
|
# @example Upsert the document.
|
14
19
|
# document.upsert
|
15
20
|
#
|
21
|
+
# @example Upsert the document without replace.
|
22
|
+
# document.upsert(replace: false)
|
23
|
+
#
|
16
24
|
# @param [ Hash ] options The validation options.
|
17
25
|
#
|
26
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
27
|
+
# @option options [ true | false ] :replace Whether or not to replace the document on upsert.
|
28
|
+
#
|
18
29
|
# @return [ true ] True.
|
19
30
|
def upsert(options = {})
|
20
31
|
prepare_upsert(options) do
|
21
|
-
|
32
|
+
if options.fetch(:replace, true)
|
33
|
+
collection.find(atomic_selector).replace_one(
|
22
34
|
as_attributes, upsert: true, session: _session)
|
35
|
+
else
|
36
|
+
collection.find(atomic_selector).update_one(
|
37
|
+
{ "$set" => as_attributes }, upsert: true, session: _session)
|
38
|
+
end
|
23
39
|
end
|
24
40
|
end
|
25
41
|
|
@@ -36,8 +52,11 @@ module Mongoid
|
|
36
52
|
#
|
37
53
|
# @param [ Hash ] options The options hash.
|
38
54
|
#
|
55
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
56
|
+
#
|
39
57
|
# @return [ true | false ] If the operation succeeded.
|
40
58
|
def prepare_upsert(options = {})
|
59
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
41
60
|
return false if performing_validations?(options) && invalid?(:upsert)
|
42
61
|
result = run_callbacks(:upsert) do
|
43
62
|
yield(self)
|
data/lib/mongoid/persistable.rb
CHANGED
@@ -161,6 +161,8 @@ module Mongoid
|
|
161
161
|
# @param [ Object ] result The result of the operation.
|
162
162
|
# @param [ Hash ] options The options.
|
163
163
|
#
|
164
|
+
# @option options [ true | false ] :validate Whether or not to validate.
|
165
|
+
#
|
164
166
|
# @return [ true ] true.
|
165
167
|
def post_process_persist(result, options = {})
|
166
168
|
post_persist unless result == false
|
@@ -180,6 +182,7 @@ module Mongoid
|
|
180
182
|
#
|
181
183
|
# @return [ Object ] The result of the operation.
|
182
184
|
def prepare_atomic_operation
|
185
|
+
raise Errors::ReadonlyDocument.new(self.class) if readonly? && !Mongoid.legacy_readonly
|
183
186
|
operations = yield({})
|
184
187
|
persist_or_delay_atomic_operation(operations)
|
185
188
|
self
|
data/lib/mongoid/query_cache.rb
CHANGED
@@ -14,6 +14,7 @@ module Mongoid
|
|
14
14
|
#
|
15
15
|
# @return [ nil ] Always nil.
|
16
16
|
def clear_cache
|
17
|
+
Mongoid::Warnings.warn_mongoid_query_cache_clear
|
17
18
|
Mongo::QueryCache.clear
|
18
19
|
end
|
19
20
|
|
@@ -24,6 +25,7 @@ module Mongoid
|
|
24
25
|
#
|
25
26
|
# @param [ true | false ] value The enabled value.
|
26
27
|
def enabled=(value)
|
28
|
+
Mongoid::Warnings.warn_mongoid_query_cache
|
27
29
|
Mongo::QueryCache.enabled = value
|
28
30
|
end
|
29
31
|
|
@@ -34,6 +36,7 @@ module Mongoid
|
|
34
36
|
#
|
35
37
|
# @return [ true | false ] If the cache is enabled.
|
36
38
|
def enabled?
|
39
|
+
Mongoid::Warnings.warn_mongoid_query_cache
|
37
40
|
Mongo::QueryCache.enabled?
|
38
41
|
end
|
39
42
|
|
@@ -44,6 +47,7 @@ module Mongoid
|
|
44
47
|
#
|
45
48
|
# @return [ Object ] The result of the block.
|
46
49
|
def cache(&block)
|
50
|
+
Mongoid::Warnings.warn_mongoid_query_cache
|
47
51
|
Mongo::QueryCache.cache(&block)
|
48
52
|
end
|
49
53
|
|
@@ -54,6 +58,7 @@ module Mongoid
|
|
54
58
|
#
|
55
59
|
# @return [ Object ] The result of the block.
|
56
60
|
def uncached(&block)
|
61
|
+
Mongoid::Warnings.warn_mongoid_query_cache
|
57
62
|
Mongo::QueryCache.uncached(&block)
|
58
63
|
end
|
59
64
|
end
|
@@ -61,4 +66,3 @@ module Mongoid
|
|
61
66
|
Middleware = Mongo::QueryCache::Middleware
|
62
67
|
end
|
63
68
|
end
|
64
|
-
|
@@ -25,7 +25,7 @@ namespace :db do
|
|
25
25
|
|
26
26
|
unless Rake::Task.task_defined?("db:setup")
|
27
27
|
desc "Create the database, and initialize with the seed data"
|
28
|
-
task :setup => [ "db:create", "mongoid:create_indexes", "db:seed" ]
|
28
|
+
task :setup => [ "db:create", "mongoid:create_collections", "mongoid:create_indexes", "db:seed" ]
|
29
29
|
end
|
30
30
|
|
31
31
|
unless Rake::Task.task_defined?("db:reset")
|
@@ -55,10 +55,15 @@ namespace :db do
|
|
55
55
|
|
56
56
|
unless Rake::Task.task_defined?("db:test:prepare")
|
57
57
|
namespace :test do
|
58
|
-
task :prepare => "mongoid:create_indexes"
|
58
|
+
task :prepare => ["mongoid:create_collections", "mongoid:create_indexes"]
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
unless Rake::Task.task_defined?("db:create_collections")
|
63
|
+
desc "Create collections specified in Mongoid models"
|
64
|
+
task :create_collections => "mongoid:create_collections"
|
65
|
+
end
|
66
|
+
|
62
67
|
unless Rake::Task.task_defined?("db:create_indexes")
|
63
68
|
desc "Create indexes specified in Mongoid models"
|
64
69
|
task :create_indexes => "mongoid:create_indexes"
|
data/lib/mongoid/reloadable.rb
CHANGED
@@ -16,14 +16,16 @@ 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
|
+
|
19
24
|
reloaded = _reload
|
20
25
|
if Mongoid.raise_not_found_error && (reloaded.nil? || reloaded.empty?)
|
21
26
|
shard_keys = atomic_selector.with_indifferent_access.slice(*shard_key_fields, :_id)
|
22
27
|
raise Errors::DocumentNotFound.new(self.class, _id, shard_keys)
|
23
28
|
end
|
24
|
-
|
25
|
-
reset_atomic_updates!
|
26
|
-
|
27
29
|
@attributes = reloaded
|
28
30
|
@attributes_before_type_cast = @attributes.dup
|
29
31
|
@changed_attributes = {}
|
data/lib/mongoid/stateful.rb
CHANGED
@@ -95,6 +95,23 @@ module Mongoid
|
|
95
95
|
!_parent.delayed_atomic_sets[atomic_path]
|
96
96
|
end
|
97
97
|
|
98
|
+
# Flags the document as readonly. Will cause a ReadonlyDocument error to be
|
99
|
+
# raised if the document is attempted to be saved, updated or destroyed.
|
100
|
+
#
|
101
|
+
# @example Flag the document as readonly.
|
102
|
+
# document.readonly!
|
103
|
+
#
|
104
|
+
# @return [ true | false ] true if the document was successfully marked
|
105
|
+
# readonly, false otherwise.
|
106
|
+
def readonly!
|
107
|
+
if Mongoid.legacy_readonly
|
108
|
+
Mongoid::Warnings.warn_legacy_readonly
|
109
|
+
false
|
110
|
+
else
|
111
|
+
@readonly = true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
98
115
|
# Is the document readonly?
|
99
116
|
#
|
100
117
|
# @example Is the document readonly?
|
@@ -102,7 +119,11 @@ module Mongoid
|
|
102
119
|
#
|
103
120
|
# @return [ true | false ] If the document is readonly.
|
104
121
|
def readonly?
|
105
|
-
|
122
|
+
if Mongoid.legacy_readonly
|
123
|
+
__selected_fields != nil
|
124
|
+
else
|
125
|
+
@readonly ||= false
|
126
|
+
end
|
106
127
|
end
|
107
128
|
|
108
129
|
# Determine if the document can be set.
|
@@ -5,6 +5,11 @@ namespace :db do
|
|
5
5
|
task :load_models do
|
6
6
|
end
|
7
7
|
|
8
|
+
desc "Create collections for Mongoid models"
|
9
|
+
task :create_collections => [:environment, :load_models] do
|
10
|
+
::Mongoid::Tasks::Database.create_collections
|
11
|
+
end
|
12
|
+
|
8
13
|
desc "Create indexes specified in Mongoid models"
|
9
14
|
task :create_indexes => [:environment, :load_models] do
|
10
15
|
::Mongoid::Tasks::Database.create_indexes
|
@@ -34,5 +39,12 @@ namespace :db do
|
|
34
39
|
task :purge => :environment do
|
35
40
|
::Mongoid.purge!
|
36
41
|
end
|
42
|
+
|
43
|
+
namespace :create_collections do
|
44
|
+
desc "Drop and create collections for Mongoid models"
|
45
|
+
task :force => [:environment, :load_models] do
|
46
|
+
::Mongoid::Tasks::Database.create_collections(force: true)
|
47
|
+
end
|
48
|
+
end
|
37
49
|
end
|
38
50
|
end
|
@@ -5,6 +5,26 @@ module Mongoid
|
|
5
5
|
module Database
|
6
6
|
extend self
|
7
7
|
|
8
|
+
# Create collections for each model given the provided globs and the class is
|
9
|
+
# not embedded.
|
10
|
+
#
|
11
|
+
# @param [ Array<Mongoid::Document> ] models. Array of document classes for
|
12
|
+
# which collections should be created. Defaulted to all document classes
|
13
|
+
# in the application.
|
14
|
+
# @param [ true | false ] force If true, the method will drop existing
|
15
|
+
# collections before creating new ones. If false, the method will create
|
16
|
+
# only new collection (that do not exist in the database).
|
17
|
+
def create_collections(models = ::Mongoid.models, force: false)
|
18
|
+
models.each do |model|
|
19
|
+
if !model.embedded? || model.cyclic?
|
20
|
+
model.create_collection(force: force)
|
21
|
+
logger.info("MONGOID: Created collection for #{model}:")
|
22
|
+
else
|
23
|
+
logger.info("MONGOID: collection options ignored on: #{model}, please define in the root model.")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
8
28
|
# Create indexes for each model given the provided globs and the class is
|
9
29
|
# not embedded.
|
10
30
|
#
|
@@ -22,20 +22,13 @@ module Mongoid
|
|
22
22
|
# @example Set the created at time.
|
23
23
|
# person.set_created_at
|
24
24
|
def set_created_at
|
25
|
-
if
|
25
|
+
if !timeless? && !created_at
|
26
26
|
time = Time.configured.now
|
27
27
|
self.updated_at = time if is_a?(Updated) && !updated_at_changed?
|
28
28
|
self.created_at = time
|
29
29
|
end
|
30
30
|
clear_timeless_option
|
31
31
|
end
|
32
|
-
|
33
|
-
# Is the created timestamp able to be set?
|
34
|
-
#
|
35
|
-
# @return [ true, false ] If the timestamp can be set.
|
36
|
-
def able_to_set_created_at?
|
37
|
-
!frozen? && !timeless? && !created_at
|
38
|
-
end
|
39
32
|
end
|
40
33
|
end
|
41
34
|
end
|
data/lib/mongoid/traversable.rb
CHANGED
@@ -300,18 +300,6 @@ module Mongoid
|
|
300
300
|
!!(Mongoid::Document > superclass)
|
301
301
|
end
|
302
302
|
|
303
|
-
# Returns the root class of the STI tree that the current
|
304
|
-
# class participates in. If the class is not an STI subclass, this
|
305
|
-
# returns the class itself.
|
306
|
-
#
|
307
|
-
# @return [ Mongoid::Document ] the root of the STI tree
|
308
|
-
def root_class
|
309
|
-
root = self
|
310
|
-
root = root.superclass while root.hereditary?
|
311
|
-
|
312
|
-
root
|
313
|
-
end
|
314
|
-
|
315
303
|
# When inheriting, we want to copy the fields from the parent class and
|
316
304
|
# set the on the child to start, mimicking the behavior of the old
|
317
305
|
# class_inheritable_accessor that was deprecated in Rails edge.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
|
5
|
+
# @api private
|
6
|
+
module Utils
|
7
|
+
|
8
|
+
# This function should be used if you need to measure time.
|
9
|
+
# @example Calculate elapsed time.
|
10
|
+
# starting = Utils.monotonic_time
|
11
|
+
# # do something time consuming
|
12
|
+
# ending = Utils.monotonic_time
|
13
|
+
# puts "It took #{(ending - starting).to_i} seconds"
|
14
|
+
#
|
15
|
+
# @see https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
|
16
|
+
#
|
17
|
+
# @return [Float] seconds according to monotonic clock
|
18
|
+
module_function def monotonic_time
|
19
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|