mongoid 8.0.7 → 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 +0 -25
- data/lib/config/locales/en.yml +46 -14
- data/lib/mongoid/association/accessors.rb +2 -2
- data/lib/mongoid/association/builders.rb +1 -1
- 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 +2 -2
- data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
- data/lib/mongoid/association/reflections.rb +2 -2
- data/lib/mongoid/atomic.rb +0 -7
- 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 +99 -28
- 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/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/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 +53 -24
- data/lib/mongoid/findable.rb +27 -3
- data/lib/mongoid/interceptable.rb +10 -118
- 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/utils.rb +22 -0
- data/lib/mongoid/validatable/macros.rb +5 -5
- data/lib/mongoid/validatable.rb +4 -1
- 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 -2
- data/spec/integration/callbacks_models.rb +37 -0
- data/spec/integration/callbacks_spec.rb +126 -12
- data/spec/integration/discriminator_key_spec.rb +4 -5
- data/spec/integration/i18n_fallbacks_spec.rb +3 -2
- 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_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 +5 -27
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +9 -50
- data/spec/mongoid/association/syncable_spec.rb +1 -1
- 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/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 +173 -362
- 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 +9 -30
- 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_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/uniqueness_spec.rb +2 -3
- data/spec/mongoid_spec.rb +36 -10
- 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/book.rb +1 -0
- data/spec/support/models/building.rb +2 -0
- data/spec/support/models/cover.rb +10 -0
- data/spec/support/models/person.rb +0 -1
- data/spec/support/models/product.rb +1 -0
- data.tar.gz.sig +0 -0
- metadata +685 -651
- metadata.gz.sig +0 -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
|
@@ -43,46 +43,22 @@ module Mongoid
|
|
|
43
43
|
# @return [ true | false ] True if pending, false if not.
|
|
44
44
|
def pending_attribute?(key, value)
|
|
45
45
|
name = key.to_s
|
|
46
|
+
|
|
46
47
|
aliased = if aliased_associations.key?(name)
|
|
47
48
|
aliased_associations[name]
|
|
48
49
|
else
|
|
49
50
|
name
|
|
50
51
|
end
|
|
52
|
+
|
|
51
53
|
if relations.has_key?(aliased)
|
|
52
|
-
|
|
54
|
+
pending_relations[name] = value
|
|
53
55
|
return true
|
|
54
56
|
end
|
|
55
57
|
if nested_attributes.has_key?(aliased)
|
|
56
|
-
set_pending_nested(name, aliased, value)
|
|
57
|
-
return true
|
|
58
|
-
end
|
|
59
|
-
false
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Set value of the pending relation.
|
|
63
|
-
#
|
|
64
|
-
# @param [ Symbol ] name The name of the relation.
|
|
65
|
-
# @param [ Symbol ] aliased The aliased name of the relation.
|
|
66
|
-
# @param [ Object ] value The value of the relation.
|
|
67
|
-
def set_pending_relation(name, aliased, value)
|
|
68
|
-
if stored_as_associations.include?(name)
|
|
69
|
-
pending_relations[aliased] = value
|
|
70
|
-
else
|
|
71
|
-
pending_relations[name] = value
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Set value of the pending nested attribute.
|
|
76
|
-
#
|
|
77
|
-
# @param [ Symbol ] name The name of the nested attribute.
|
|
78
|
-
# @param [ Symbol ] aliased The aliased name of the nested attribute.
|
|
79
|
-
# @param [ Object ] value The value of the nested attribute.
|
|
80
|
-
def set_pending_nested(name, aliased, value)
|
|
81
|
-
if stored_as_associations.include?(name)
|
|
82
|
-
pending_nested[aliased] = value
|
|
83
|
-
else
|
|
84
58
|
pending_nested[name] = value
|
|
59
|
+
return true
|
|
85
60
|
end
|
|
61
|
+
return false
|
|
86
62
|
end
|
|
87
63
|
|
|
88
64
|
# Get all the pending associations that need to be set.
|
|
@@ -6,7 +6,7 @@ module Mongoid
|
|
|
6
6
|
# This module defines projection helpers.
|
|
7
7
|
#
|
|
8
8
|
# Projection rules are rather non-trivial. See
|
|
9
|
-
# https://
|
|
9
|
+
# https://www.mongodb.com/docs/manual/reference/method/db.collection.find/#find-projection
|
|
10
10
|
# for server documentation.
|
|
11
11
|
# 4.4 server (and presumably all older ones) requires that a projection
|
|
12
12
|
# for content fields is either exclusionary or inclusionary, i.e. one
|
|
@@ -61,7 +61,7 @@ module Mongoid
|
|
|
61
61
|
# attr_readonly :name, :genre
|
|
62
62
|
# end
|
|
63
63
|
#
|
|
64
|
-
# @param [
|
|
64
|
+
# @param [ Symbol... ] *names The names of the fields.
|
|
65
65
|
def attr_readonly(*names)
|
|
66
66
|
names.each do |name|
|
|
67
67
|
readonly_attributes << database_field_name(name)
|
data/lib/mongoid/attributes.rb
CHANGED
|
@@ -177,8 +177,14 @@ module Mongoid
|
|
|
177
177
|
attribute_will_change!(field_name)
|
|
178
178
|
end
|
|
179
179
|
if localized
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
present = fields[field_name].try(:localize_present?)
|
|
181
|
+
loc_key, loc_val = typed_value.first
|
|
182
|
+
if present && loc_val.blank?
|
|
183
|
+
attributes[field_name]&.delete(loc_key)
|
|
184
|
+
else
|
|
185
|
+
attributes[field_name] ||= {}
|
|
186
|
+
attributes[field_name].merge!(typed_value)
|
|
187
|
+
end
|
|
182
188
|
else
|
|
183
189
|
attributes[field_name] = typed_value
|
|
184
190
|
end
|
data/lib/mongoid/changeable.rb
CHANGED
|
@@ -68,9 +68,13 @@ module Mongoid
|
|
|
68
68
|
# @example Move the changes to previous.
|
|
69
69
|
# person.move_changes
|
|
70
70
|
def move_changes
|
|
71
|
+
@changes_before_last_save = @previous_changes
|
|
71
72
|
@previous_changes = changes
|
|
73
|
+
@attributes_before_last_save = @previous_attributes
|
|
72
74
|
@previous_attributes = attributes.dup
|
|
73
|
-
|
|
75
|
+
Atomic::UPDATES.each do |update|
|
|
76
|
+
send(update).clear
|
|
77
|
+
end
|
|
74
78
|
changed_attributes.clear
|
|
75
79
|
end
|
|
76
80
|
|
|
@@ -131,6 +135,72 @@ module Mongoid
|
|
|
131
135
|
mods
|
|
132
136
|
end
|
|
133
137
|
|
|
138
|
+
# Returns the original value of an attribute before the last save.
|
|
139
|
+
#
|
|
140
|
+
# This method is useful in after callbacks to get the original value of
|
|
141
|
+
# an attribute before the save that triggered the callbacks to run.
|
|
142
|
+
#
|
|
143
|
+
# @param [ Symbol | String ] attr The name of the attribute.
|
|
144
|
+
#
|
|
145
|
+
# @return [ Object ] Value of the attribute before the last save.
|
|
146
|
+
def attribute_before_last_save(attr)
|
|
147
|
+
attr = database_field_name(attr)
|
|
148
|
+
attributes_before_last_save[attr]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Returns the change to an attribute during the last save.
|
|
152
|
+
#
|
|
153
|
+
# @param [ Symbol | String ] attr The name of the attribute.
|
|
154
|
+
#
|
|
155
|
+
# @return [ Array<Object> | nil ] If the attribute was changed, returns
|
|
156
|
+
# an array containing the original value and the saved value, otherwise nil.
|
|
157
|
+
def saved_change_to_attribute(attr)
|
|
158
|
+
attr = database_field_name(attr)
|
|
159
|
+
previous_changes[attr]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Returns whether this attribute changed during the last save.
|
|
163
|
+
#
|
|
164
|
+
# This method is useful in after callbacks, to see the change
|
|
165
|
+
# in an attribute during the save that triggered the callbacks to run.
|
|
166
|
+
#
|
|
167
|
+
# @param [ String ] attr The name of the attribute.
|
|
168
|
+
# @param **kwargs The optional keyword arguments.
|
|
169
|
+
#
|
|
170
|
+
# @option **kwargs [ Object ] :from The object the attribute was changed from.
|
|
171
|
+
# @option **kwargs [ Object ] :to The object the attribute was changed to.
|
|
172
|
+
#
|
|
173
|
+
# @return [ true | false ] Whether the attribute has changed during the last save.
|
|
174
|
+
def saved_change_to_attribute?(attr, **kwargs)
|
|
175
|
+
changes = saved_change_to_attribute(attr)
|
|
176
|
+
return false unless changes.is_a?(Array)
|
|
177
|
+
if kwargs.key?(:from) && kwargs.key?(:to)
|
|
178
|
+
changes.first == kwargs[:from] && changes.last == kwargs[:to]
|
|
179
|
+
elsif kwargs.key?(:from)
|
|
180
|
+
changes.first == kwargs[:from]
|
|
181
|
+
elsif kwargs.key?(:to)
|
|
182
|
+
changes.last == kwargs[:to]
|
|
183
|
+
else
|
|
184
|
+
true
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Returns whether this attribute change the next time we save.
|
|
189
|
+
#
|
|
190
|
+
# This method is useful in validations and before callbacks to determine
|
|
191
|
+
# if the next call to save will change a particular attribute.
|
|
192
|
+
#
|
|
193
|
+
# @param [ String ] attr The name of the attribute.
|
|
194
|
+
# @param **kwargs The optional keyword arguments.
|
|
195
|
+
#
|
|
196
|
+
# @option **kwargs [ Object ] :from The object the attribute was changed from.
|
|
197
|
+
# @option **kwargs [ Object ] :to The object the attribute was changed to.
|
|
198
|
+
#
|
|
199
|
+
# @return [ true | false ] Whether the attribute change the next time we save.
|
|
200
|
+
def will_save_change_to_attribute?(attr, **kwargs)
|
|
201
|
+
attribute_changed?(attr, **kwargs)
|
|
202
|
+
end
|
|
203
|
+
|
|
134
204
|
private
|
|
135
205
|
|
|
136
206
|
# Get attributes of the document before the document was saved.
|
|
@@ -140,6 +210,14 @@ module Mongoid
|
|
|
140
210
|
@previous_attributes ||= {}
|
|
141
211
|
end
|
|
142
212
|
|
|
213
|
+
def changes_before_last_save
|
|
214
|
+
@changes_before_last_save ||= {}
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def attributes_before_last_save
|
|
218
|
+
@attributes_before_last_save ||= {}
|
|
219
|
+
end
|
|
220
|
+
|
|
143
221
|
# Get the old and new value for the provided attribute.
|
|
144
222
|
#
|
|
145
223
|
# @example Get the attribute change.
|
|
@@ -159,12 +237,24 @@ module Mongoid
|
|
|
159
237
|
# model.attribute_changed?("name")
|
|
160
238
|
#
|
|
161
239
|
# @param [ String ] attr The name of the attribute.
|
|
240
|
+
# @param **kwargs The optional keyword arguments.
|
|
241
|
+
#
|
|
242
|
+
# @option **kwargs [ Object ] :from The object the attribute was changed from.
|
|
243
|
+
# @option **kwargs [ Object ] :to The object the attribute was changed to.
|
|
162
244
|
#
|
|
163
245
|
# @return [ true | false ] Whether the attribute has changed.
|
|
164
|
-
def attribute_changed?(attr)
|
|
246
|
+
def attribute_changed?(attr, **kwargs)
|
|
165
247
|
attr = database_field_name(attr)
|
|
166
248
|
return false unless changed_attributes.key?(attr)
|
|
167
|
-
changed_attributes[attr]
|
|
249
|
+
return false if changed_attributes[attr] == attributes[attr]
|
|
250
|
+
if kwargs.key?(:from)
|
|
251
|
+
return false if changed_attributes[attr] != kwargs[:from]
|
|
252
|
+
end
|
|
253
|
+
if kwargs.key?(:to)
|
|
254
|
+
return false if attributes[attr] != kwargs[:to]
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
true
|
|
168
258
|
end
|
|
169
259
|
|
|
170
260
|
# Get whether or not the field has a different value from the default.
|
|
@@ -300,8 +390,11 @@ module Mongoid
|
|
|
300
390
|
# @param [ String ] meth The name of the accessor.
|
|
301
391
|
def create_dirty_change_check(name, meth)
|
|
302
392
|
generated_methods.module_eval do
|
|
303
|
-
re_define_method("#{meth}_changed?") do
|
|
304
|
-
attribute_changed?(name)
|
|
393
|
+
re_define_method("#{meth}_changed?") do |**kwargs|
|
|
394
|
+
attribute_changed?(name, **kwargs)
|
|
395
|
+
end
|
|
396
|
+
re_define_method("will_save_change_to_#{meth}?") do |**kwargs|
|
|
397
|
+
will_save_change_to_attribute?(name, **kwargs)
|
|
305
398
|
end
|
|
306
399
|
end
|
|
307
400
|
end
|
|
@@ -336,6 +429,15 @@ module Mongoid
|
|
|
336
429
|
re_define_method("#{meth}_previously_was") do
|
|
337
430
|
attribute_previously_was(name)
|
|
338
431
|
end
|
|
432
|
+
re_define_method("#{meth}_before_last_save") do
|
|
433
|
+
attribute_before_last_save(name)
|
|
434
|
+
end
|
|
435
|
+
re_define_method("saved_change_to_#{meth}") do
|
|
436
|
+
saved_change_to_attribute(name)
|
|
437
|
+
end
|
|
438
|
+
re_define_method("saved_change_to_#{meth}?") do |**kwargs|
|
|
439
|
+
saved_change_to_attribute?(name, **kwargs)
|
|
440
|
+
end
|
|
339
441
|
end
|
|
340
442
|
end
|
|
341
443
|
|
|
@@ -6,10 +6,7 @@ module Mongoid
|
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
8
|
included do
|
|
9
|
-
|
|
10
|
-
cattr_accessor :storage_options, instance_writer: false do
|
|
11
|
-
storage_options_defaults
|
|
12
|
-
end
|
|
9
|
+
class_attribute :storage_options, instance_writer: false, default: storage_options_defaults
|
|
13
10
|
end
|
|
14
11
|
|
|
15
12
|
module ClassMethods
|
|
@@ -49,7 +46,7 @@ module Mongoid
|
|
|
49
46
|
# @return [ Class ] The model class.
|
|
50
47
|
def store_in(options)
|
|
51
48
|
Validators::Storage.validate(self, options)
|
|
52
|
-
storage_options.merge
|
|
49
|
+
self.storage_options = self.storage_options.merge(options)
|
|
53
50
|
end
|
|
54
51
|
|
|
55
52
|
# Reset the store_in options
|
|
@@ -9,7 +9,7 @@ module Mongoid
|
|
|
9
9
|
extend self
|
|
10
10
|
|
|
11
11
|
# The valid options for storage.
|
|
12
|
-
VALID_OPTIONS = [ :collection, :database, :client ].freeze
|
|
12
|
+
VALID_OPTIONS = [ :collection, :collection_options, :database, :client ].freeze
|
|
13
13
|
|
|
14
14
|
# Validate the options provided to :store_in.
|
|
15
15
|
#
|
|
@@ -20,21 +20,9 @@ module Mongoid
|
|
|
20
20
|
# @param [ Hash | String | Symbol ] options The provided options.
|
|
21
21
|
def validate(klass, options)
|
|
22
22
|
valid_keys?(options) or raise Errors::InvalidStorageOptions.new(klass, options)
|
|
23
|
-
valid_parent?(klass) or raise Errors::InvalidStorageParent.new(klass)
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
private
|
|
27
|
-
# Determine if the current klass is valid to change store_in
|
|
28
|
-
# options
|
|
29
|
-
#
|
|
30
|
-
# @api private
|
|
31
|
-
#
|
|
32
|
-
# @param [ Class ] klass
|
|
33
|
-
#
|
|
34
|
-
# @return [ true | false ] If the class is valid.
|
|
35
|
-
def valid_parent?(klass)
|
|
36
|
-
!klass.superclass.include?(Mongoid::Document)
|
|
37
|
-
end
|
|
38
26
|
|
|
39
27
|
# Determine if all keys in the options hash are valid.
|
|
40
28
|
#
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mongoid
|
|
4
|
+
|
|
5
|
+
# Encapsulates behavior around defining collections.
|
|
6
|
+
module CollectionConfigurable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
# Create the collection for the called upon Mongoid model.
|
|
11
|
+
#
|
|
12
|
+
# This method does not re-create existing collections.
|
|
13
|
+
#
|
|
14
|
+
# If the document includes `store_in` macro with `collection_options` key,
|
|
15
|
+
# these options are used when creating the collection.
|
|
16
|
+
#
|
|
17
|
+
# @param [ true | false ] force If true, the method will drop existing
|
|
18
|
+
# collections before creating new ones. If false, the method will create
|
|
19
|
+
# only new collection (that do not exist in the database).
|
|
20
|
+
#
|
|
21
|
+
# @raise [ Errors::CreateCollectionFailure ] If collection creation failed.
|
|
22
|
+
# @raise [ Errors::DropCollectionFailure ] If an attempt to drop collection failed.
|
|
23
|
+
def create_collection(force: false)
|
|
24
|
+
if collection_name.empty?
|
|
25
|
+
# This is most probably an anonymous class, we ignore them.
|
|
26
|
+
return
|
|
27
|
+
end
|
|
28
|
+
if collection_name.match(/^system\./)
|
|
29
|
+
# We do not do anything with system collections.
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
if force
|
|
33
|
+
collection.drop
|
|
34
|
+
end
|
|
35
|
+
if coll_options = collection.database.list_collections(filter: { name: collection_name.to_s }).first
|
|
36
|
+
if force
|
|
37
|
+
raise Errors::DropCollectionFailure.new(collection_name)
|
|
38
|
+
else
|
|
39
|
+
logger.debug(
|
|
40
|
+
"MONGOID: Collection '#{collection_name}' already exists " +
|
|
41
|
+
"in database '#{database_name}' with options '#{coll_options}'."
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
begin
|
|
46
|
+
collection.database[collection_name, storage_options.fetch(:collection_options, {})].create
|
|
47
|
+
rescue Mongo::Error::OperationFailure => e
|
|
48
|
+
raise Errors::CreateCollectionFailure.new(
|
|
49
|
+
collection_name,
|
|
50
|
+
storage_options[:collection_options],
|
|
51
|
+
e
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/mongoid/composable.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "mongoid/changeable"
|
|
4
|
+
require "mongoid/collection_configurable"
|
|
4
5
|
require "mongoid/findable"
|
|
5
6
|
require "mongoid/indexable"
|
|
6
7
|
require "mongoid/inspectable"
|
|
@@ -36,6 +37,7 @@ module Mongoid
|
|
|
36
37
|
include Atomic
|
|
37
38
|
include Changeable
|
|
38
39
|
include Clients
|
|
40
|
+
include CollectionConfigurable
|
|
39
41
|
include Attributes
|
|
40
42
|
include Evolvable
|
|
41
43
|
include Fields
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mongoid
|
|
4
|
+
module Config
|
|
5
|
+
|
|
6
|
+
# Encapsulates logic for loading defaults.
|
|
7
|
+
module Defaults
|
|
8
|
+
|
|
9
|
+
# Load the defaults for the feature flags in the given Mongoid version.
|
|
10
|
+
# Note that this method will load the *new* functionality introduced in
|
|
11
|
+
# the given Mongoid version.
|
|
12
|
+
#
|
|
13
|
+
# @param [ String | Float ] The version number as X.y.
|
|
14
|
+
#
|
|
15
|
+
# raises [ ArgumentError ] if an invalid version is given.
|
|
16
|
+
def load_defaults(version)
|
|
17
|
+
# Note that for 7.x, since all of the feature flag defaults have been
|
|
18
|
+
# flipped to the new functionality, all of the settings for those
|
|
19
|
+
# versions are to give old functionality. Because of this, it is
|
|
20
|
+
# possible to recurse to later version to get all of the options to
|
|
21
|
+
# turn off. Note that this won't be true when adding feature flags to
|
|
22
|
+
# 9.x, since the default will be the old functionality until the next
|
|
23
|
+
# major version is released. More likely, the recursion will have to go
|
|
24
|
+
# in the other direction (towards earlier versions).
|
|
25
|
+
|
|
26
|
+
case version.to_s
|
|
27
|
+
when "7.3"
|
|
28
|
+
# flags introduced in 7.4 - old functionality
|
|
29
|
+
self.broken_aggregables = true
|
|
30
|
+
self.broken_alias_handling = true
|
|
31
|
+
self.broken_and = true
|
|
32
|
+
self.broken_scoping = true
|
|
33
|
+
self.broken_updates = true
|
|
34
|
+
self.compare_time_by_ms = false
|
|
35
|
+
self.legacy_pluck_distinct = true
|
|
36
|
+
self.legacy_triple_equals = true
|
|
37
|
+
self.object_id_as_json_oid = true
|
|
38
|
+
|
|
39
|
+
load_defaults "7.4"
|
|
40
|
+
when "7.4"
|
|
41
|
+
# flags introduced in 7.5 - old functionality
|
|
42
|
+
self.legacy_attributes = true
|
|
43
|
+
self.overwrite_chained_operators = true
|
|
44
|
+
|
|
45
|
+
load_defaults "7.5"
|
|
46
|
+
when "7.5"
|
|
47
|
+
# flags introduced in 8.0 - old functionality
|
|
48
|
+
self.map_big_decimal_to_decimal128 = false
|
|
49
|
+
when "8.0"
|
|
50
|
+
# All flag defaults currently reflect 8.0 behavior.
|
|
51
|
+
when "8.1"
|
|
52
|
+
# flags introduced in 8.1 - new functionality
|
|
53
|
+
self.legacy_readonly = false
|
|
54
|
+
else
|
|
55
|
+
raise ArgumentError, "Unknown version: #{version}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -25,8 +25,6 @@ module Mongoid
|
|
|
25
25
|
# @param [ Hash ] options Extras for the option.
|
|
26
26
|
#
|
|
27
27
|
# @option options [ Object ] :default The default value.
|
|
28
|
-
# @option options [ Proc | nil ] :on_change The callback to invoke when the
|
|
29
|
-
# setter is invoked.
|
|
30
28
|
def option(name, options = {})
|
|
31
29
|
defaults[name] = settings[name] = options[:default]
|
|
32
30
|
|
|
@@ -40,7 +38,6 @@ module Mongoid
|
|
|
40
38
|
|
|
41
39
|
define_method("#{name}=") do |value|
|
|
42
40
|
settings[name] = value
|
|
43
|
-
options[:on_change]&.call(value)
|
|
44
41
|
end
|
|
45
42
|
|
|
46
43
|
define_method("#{name}?") do
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mongoid
|
|
4
|
+
module Config
|
|
5
|
+
module Validators
|
|
6
|
+
|
|
7
|
+
# Validator for async query executor configuration.
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
module AsyncQueryExecutor
|
|
11
|
+
extend self
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def validate(options)
|
|
15
|
+
if options.key?(:async_query_executor)
|
|
16
|
+
if options[:async_query_executor].to_sym == :immediate && !options[:global_executor_concurrency].nil?
|
|
17
|
+
raise Errors::InvalidGlobalExecutorConcurrency
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/mongoid/config.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "mongoid/config/defaults"
|
|
3
4
|
require "mongoid/config/environment"
|
|
4
5
|
require "mongoid/config/options"
|
|
5
6
|
require "mongoid/config/validators"
|
|
@@ -11,6 +12,7 @@ module Mongoid
|
|
|
11
12
|
module Config
|
|
12
13
|
extend Forwardable
|
|
13
14
|
extend Options
|
|
15
|
+
extend Defaults
|
|
14
16
|
extend self
|
|
15
17
|
|
|
16
18
|
def_delegators ::Mongoid, :logger, :logger=
|
|
@@ -70,6 +72,7 @@ module Mongoid
|
|
|
70
72
|
|
|
71
73
|
# Use ActiveSupport's time zone in time operations instead of the
|
|
72
74
|
# Ruby default time zone.
|
|
75
|
+
# @deprecated
|
|
73
76
|
option :use_activesupport_time_zone, default: true
|
|
74
77
|
|
|
75
78
|
# Return stored times as UTC.
|
|
@@ -125,35 +128,52 @@ module Mongoid
|
|
|
125
128
|
# always return a Hash.
|
|
126
129
|
option :legacy_attributes, default: false
|
|
127
130
|
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
|
|
131
|
+
# Sets the async_query_executor for the application. By default the thread pool executor
|
|
132
|
+
# is set to `:immediate. Options are:
|
|
133
|
+
#
|
|
134
|
+
# - :immediate - Initializes a single +Concurrent::ImmediateExecutor+
|
|
135
|
+
# - :global_thread_pool - Initializes a single +Concurrent::ThreadPoolExecutor+
|
|
136
|
+
# that uses the +async_query_concurrency+ for the +max_threads+ value.
|
|
137
|
+
option :async_query_executor, default: :immediate
|
|
138
|
+
|
|
139
|
+
# Defines how many asynchronous queries can be executed concurrently.
|
|
140
|
+
# This option should be set only if `async_query_executor` is set
|
|
141
|
+
# to `:global_thread_pool`.
|
|
142
|
+
option :global_executor_concurrency, default: nil
|
|
143
|
+
|
|
144
|
+
# When this flag is false, a document will become read-only only once the
|
|
145
|
+
# #readonly! method is called, and an error will be raised on attempting
|
|
146
|
+
# to save or update such documents, instead of just on delete. When this
|
|
147
|
+
# flag is true, a document is only read-only if it has been projected
|
|
148
|
+
# using #only or #without, and read-only documents will not be
|
|
149
|
+
# deletable/destroyable, but they will be savable/updatable.
|
|
150
|
+
# When this feature flag is turned on, the read-only state will be reset on
|
|
151
|
+
# reload, but when it is turned off, it won't be.
|
|
152
|
+
option :legacy_readonly, default: true
|
|
153
|
+
|
|
154
|
+
# When this flag is true, any attempt to change the _id of a persisted
|
|
155
|
+
# document will raise an exception (`Errors::ImmutableAttribute`).
|
|
156
|
+
# This will be the default in 9.0. When this flag is false (the default
|
|
157
|
+
# in 8.x), changing the _id of a persisted document might be ignored,
|
|
158
|
+
# or it might work, depending on the situation.
|
|
159
|
+
option :immutable_ids, default: false
|
|
160
|
+
|
|
161
|
+
# When this flag is true, callbacks for every embedded document will be
|
|
162
|
+
# called only once, even if the embedded document is embedded in multiple
|
|
150
163
|
# documents in the root document's dependencies graph.
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
# See https://jira.mongodb.org/browse/MONGOID-
|
|
156
|
-
option :
|
|
164
|
+
# This will be the default in 9.0. Setting this flag to false restores the
|
|
165
|
+
# pre-9.0 behavior, where callbacks are called for every occurrence of an
|
|
166
|
+
# embedded document. The pre-9.0 behavior leads to a problem that for multi
|
|
167
|
+
# level nested documents callbacks are called multiple times.
|
|
168
|
+
# See https://jira.mongodb.org/browse/MONGOID-5542
|
|
169
|
+
option :prevent_multiple_calls_of_embedded_callbacks, default: false
|
|
170
|
+
|
|
171
|
+
# Returns the Config singleton, for use in the configure DSL.
|
|
172
|
+
#
|
|
173
|
+
# @return [ self ] The Config singleton.
|
|
174
|
+
def config
|
|
175
|
+
self
|
|
176
|
+
end
|
|
157
177
|
|
|
158
178
|
# Has Mongoid been configured? This is checking that at least a valid
|
|
159
179
|
# client config exists.
|
|
@@ -236,6 +256,17 @@ module Mongoid
|
|
|
236
256
|
end
|
|
237
257
|
end
|
|
238
258
|
|
|
259
|
+
# Deregister a model in the application with Mongoid.
|
|
260
|
+
#
|
|
261
|
+
# @param [ Class ] klass The model to deregister.
|
|
262
|
+
#
|
|
263
|
+
# @api private
|
|
264
|
+
def deregister_model(klass)
|
|
265
|
+
LOCK.synchronize do
|
|
266
|
+
models.delete(klass)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
239
270
|
# From a hash of settings, load all the configuration.
|
|
240
271
|
#
|
|
241
272
|
# @example Load the configuration.
|
|
@@ -308,6 +339,7 @@ module Mongoid
|
|
|
308
339
|
# @param [ Hash ] options The configuration options.
|
|
309
340
|
def options=(options)
|
|
310
341
|
if options
|
|
342
|
+
Validators::AsyncQueryExecutor.validate(options)
|
|
311
343
|
options.each_pair do |option, value|
|
|
312
344
|
Validators::Option.validate(option)
|
|
313
345
|
send("#{option}=", value)
|
|
@@ -375,5 +407,44 @@ module Mongoid
|
|
|
375
407
|
client
|
|
376
408
|
end
|
|
377
409
|
end
|
|
410
|
+
|
|
411
|
+
module DeprecatedOptions
|
|
412
|
+
OPTIONS = %i[ use_activesupport_time_zone
|
|
413
|
+
broken_aggregables
|
|
414
|
+
broken_alias_handling
|
|
415
|
+
broken_and
|
|
416
|
+
broken_scoping
|
|
417
|
+
broken_updates
|
|
418
|
+
compare_time_by_ms
|
|
419
|
+
legacy_attributes
|
|
420
|
+
legacy_pluck_distinct
|
|
421
|
+
legacy_triple_equals
|
|
422
|
+
object_id_as_json_oid
|
|
423
|
+
overwrite_chained_operators ]
|
|
424
|
+
|
|
425
|
+
if RUBY_VERSION < '3.0'
|
|
426
|
+
def self.prepended(klass)
|
|
427
|
+
klass.class_eval do
|
|
428
|
+
OPTIONS.each do |option|
|
|
429
|
+
alias_method :"#{option}_without_deprecation=", :"#{option}="
|
|
430
|
+
|
|
431
|
+
define_method(:"#{option}=") do |value|
|
|
432
|
+
Mongoid::Warnings.send(:"warn_#{option}_deprecated")
|
|
433
|
+
send(:"#{option}_without_deprecation=", value)
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
else
|
|
439
|
+
OPTIONS.each do |option|
|
|
440
|
+
define_method(:"#{option}=") do |value|
|
|
441
|
+
Mongoid::Warnings.send(:"warn_#{option}_deprecated")
|
|
442
|
+
super(value)
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
prepend DeprecatedOptions
|
|
378
449
|
end
|
|
379
450
|
end
|
|
@@ -150,7 +150,7 @@ module Mongoid
|
|
|
150
150
|
# @example Unset the field on the matches.
|
|
151
151
|
# context.unset(:name)
|
|
152
152
|
#
|
|
153
|
-
# @param [ String | Symbol | Array<String | Symbol> | Hash ] args
|
|
153
|
+
# @param [ [ String | Symbol | Array<String | Symbol> | Hash ]... ] *args
|
|
154
154
|
# The name(s) of the field(s) to unset.
|
|
155
155
|
# If a Hash is specified, its keys will be used irrespective of what
|
|
156
156
|
# each key's value is, even if the value is nil or false.
|