mongoid 8.1.1 → 8.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/mongoid/association/macros.rb +6 -0
- data/lib/mongoid/attributes/processing.rb +29 -5
- data/lib/mongoid/config/options.rb +3 -0
- data/lib/mongoid/config.rb +30 -0
- data/lib/mongoid/contextual/mongo.rb +24 -1
- data/lib/mongoid/criteria/queryable/selector.rb +1 -1
- data/lib/mongoid/criteria/queryable/storable.rb +1 -1
- data/lib/mongoid/deprecable.rb +2 -1
- data/lib/mongoid/deprecation.rb +3 -3
- data/lib/mongoid/extensions/hash.rb +24 -2
- data/lib/mongoid/fields.rb +24 -13
- data/lib/mongoid/interceptable.rb +118 -7
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/callbacks_spec.rb +21 -0
- data/spec/mongoid/attributes_spec.rb +27 -0
- data/spec/mongoid/config_spec.rb +9 -0
- data/spec/mongoid/contextual/mongo_spec.rb +89 -14
- data/spec/mongoid/criteria/queryable/selector_spec.rb +75 -2
- data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
- data/spec/mongoid/extensions/hash_spec.rb +3 -3
- data/spec/mongoid/fields_spec.rb +43 -0
- data/spec/mongoid/interceptable_spec.rb +364 -153
- data/spec/shared/lib/mrss/docker_runner.rb +1 -0
- data/spec/support/models/person.rb +1 -0
- data/spec/support/models/purse.rb +9 -0
- data.tar.gz.sig +0 -0
- metadata +10 -8
- 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: 561c6173b8a11bb858b0df7dc72cec9e96767e7780572ecbc1233c11de84fb6a
|
4
|
+
data.tar.gz: 1bc15420d04291843d26e52d1d04f2689d3e28b25db115d5a5f2c765b872fd30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 112499f5ac9998aa952c851ac4e6d64014bf35fcfeeed0b29bdb5fac5519866657b8f7fe087a001033cee7adcf1f07a7eb4b4c68dcef2611cbf36a1aef22d31c
|
7
|
+
data.tar.gz: 43f784a2d2d5782f464f064d35bd384a6711a2355f6a1cd3f9529372184928ecac9d2e74e4cf90092857733945a10c08452ede7e1a4cbba903d3617d5ccbf601
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -35,10 +35,15 @@ module Mongoid
|
|
35
35
|
# @api private
|
36
36
|
class_attribute :aliased_associations
|
37
37
|
|
38
|
+
# @return [ Set<String> ] The set of associations that are configured
|
39
|
+
# with :store_as parameter.
|
40
|
+
class_attribute :stored_as_associations
|
41
|
+
|
38
42
|
self.embedded = false
|
39
43
|
self.embedded_relations = BSON::Document.new
|
40
44
|
self.relations = BSON::Document.new
|
41
45
|
self.aliased_associations = {}
|
46
|
+
self.stored_as_associations = Set.new
|
42
47
|
end
|
43
48
|
|
44
49
|
# This is convenience for libraries still on the old API.
|
@@ -219,6 +224,7 @@ module Mongoid
|
|
219
224
|
self.relations = self.relations.merge(name => assoc)
|
220
225
|
if assoc.embedded? && assoc.respond_to?(:store_as) && assoc.store_as != name
|
221
226
|
self.aliased_associations[assoc.store_as] = name
|
227
|
+
self.stored_as_associations << assoc.store_as
|
222
228
|
end
|
223
229
|
end
|
224
230
|
end
|
@@ -43,22 +43,46 @@ 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
|
-
|
47
46
|
aliased = if aliased_associations.key?(name)
|
48
47
|
aliased_associations[name]
|
49
48
|
else
|
50
49
|
name
|
51
50
|
end
|
52
|
-
|
53
51
|
if relations.has_key?(aliased)
|
54
|
-
|
52
|
+
set_pending_relation(name, aliased, value)
|
55
53
|
return true
|
56
54
|
end
|
57
55
|
if nested_attributes.has_key?(aliased)
|
58
|
-
|
56
|
+
set_pending_nested(name, aliased, value)
|
59
57
|
return true
|
60
58
|
end
|
61
|
-
|
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
|
+
pending_nested[name] = value
|
85
|
+
end
|
62
86
|
end
|
63
87
|
|
64
88
|
# Get all the pending associations that need to be set.
|
@@ -25,6 +25,8 @@ 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.
|
28
30
|
def option(name, options = {})
|
29
31
|
defaults[name] = settings[name] = options[:default]
|
30
32
|
|
@@ -38,6 +40,7 @@ module Mongoid
|
|
38
40
|
|
39
41
|
define_method("#{name}=") do |value|
|
40
42
|
settings[name] = value
|
43
|
+
options[:on_change]&.call(value)
|
41
44
|
end
|
42
45
|
|
43
46
|
define_method("#{name}?") do
|
data/lib/mongoid/config.rb
CHANGED
@@ -128,6 +128,23 @@ module Mongoid
|
|
128
128
|
# always return a Hash.
|
129
129
|
option :legacy_attributes, default: false
|
130
130
|
|
131
|
+
# Allow BSON::Decimal128 to be parsed and returned directly in
|
132
|
+
# field values. When BSON 5 is present and the this option is set to false
|
133
|
+
# (the default), BSON::Decimal128 values in the database will be returned
|
134
|
+
# as BigDecimal.
|
135
|
+
#
|
136
|
+
# @note this option only has effect when BSON 5+ is present. Otherwise,
|
137
|
+
# the setting is ignored.
|
138
|
+
option :allow_bson5_decimal128, default: false, on_change: -> (allow) do
|
139
|
+
if BSON::VERSION >= '5.0.0'
|
140
|
+
if allow
|
141
|
+
BSON::Registry.register(BSON::Decimal128::BSON_TYPE, BSON::Decimal128)
|
142
|
+
else
|
143
|
+
BSON::Registry.register(BSON::Decimal128::BSON_TYPE, BigDecimal)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
131
148
|
# Sets the async_query_executor for the application. By default the thread pool executor
|
132
149
|
# is set to `:immediate. Options are:
|
133
150
|
#
|
@@ -168,6 +185,19 @@ module Mongoid
|
|
168
185
|
# See https://jira.mongodb.org/browse/MONGOID-5542
|
169
186
|
option :prevent_multiple_calls_of_embedded_callbacks, default: false
|
170
187
|
|
188
|
+
# When this flag is true, callbacks for embedded documents will not be
|
189
|
+
# called. This is the default in 8.x, but will be changed to false in 9.0.
|
190
|
+
#
|
191
|
+
# Setting this flag to true (as it is in 8.x) may lead to stack
|
192
|
+
# overflow errors if there are more than cicrca 1000 embedded
|
193
|
+
# documents in the root document's dependencies graph.
|
194
|
+
#
|
195
|
+
# It is strongly recommended to set this flag to false in 8.x, if you
|
196
|
+
# are not using around callbacks for embedded documents.
|
197
|
+
#
|
198
|
+
# See https://jira.mongodb.org/browse/MONGOID-5658 for more details.
|
199
|
+
option :around_callbacks_for_embeds, default: true
|
200
|
+
|
171
201
|
# Returns the Config singleton, for use in the configure DSL.
|
172
202
|
#
|
173
203
|
# @return [ self ] The Config singleton.
|
@@ -69,7 +69,12 @@ module Mongoid
|
|
69
69
|
# @return [ Integer ] The number of matches.
|
70
70
|
def count(options = {}, &block)
|
71
71
|
return super(&block) if block_given?
|
72
|
-
|
72
|
+
|
73
|
+
if valid_for_count_documents?
|
74
|
+
view.count_documents(options)
|
75
|
+
else
|
76
|
+
view.count(options)
|
77
|
+
end
|
73
78
|
end
|
74
79
|
|
75
80
|
# Get the estimated number of documents matching the query.
|
@@ -1046,6 +1051,24 @@ module Mongoid
|
|
1046
1051
|
limit ? docs : docs.first
|
1047
1052
|
end
|
1048
1053
|
|
1054
|
+
# Queries whether the current context is valid for use with
|
1055
|
+
# the #count_documents? predicate. A context is valid if it
|
1056
|
+
# does not include a `$where` operator.
|
1057
|
+
#
|
1058
|
+
# @return [ true | false ] whether or not the current context
|
1059
|
+
# excludes a `$where` operator.
|
1060
|
+
def valid_for_count_documents?(hash = view.filter)
|
1061
|
+
# Note that `view.filter` is a BSON::Document, and all keys in a
|
1062
|
+
# BSON::Document are strings; we don't need to worry about symbol
|
1063
|
+
# representations of `$where`.
|
1064
|
+
hash.keys.each do |key|
|
1065
|
+
return false if key == '$where'
|
1066
|
+
return false if hash[key].is_a?(Hash) && !valid_for_count_documents?(hash[key])
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
true
|
1070
|
+
end
|
1071
|
+
|
1049
1072
|
def raise_document_not_found_error
|
1050
1073
|
raise Errors::DocumentNotFound.new(klass, nil, nil)
|
1051
1074
|
end
|
@@ -47,7 +47,7 @@ module Mongoid
|
|
47
47
|
if value.is_a?(Hash) && selector[field].is_a?(Hash) &&
|
48
48
|
value.keys.all? { |key|
|
49
49
|
key_s = key.to_s
|
50
|
-
key_s.start_with?('$') && !selector[field].
|
50
|
+
key_s.start_with?('$') && !selector[field].keys.map(&:to_s).include?(key_s)
|
51
51
|
}
|
52
52
|
then
|
53
53
|
# Multiple operators can be combined on the same field by
|
data/lib/mongoid/deprecable.rb
CHANGED
@@ -27,7 +27,8 @@ module Mongoid
|
|
27
27
|
# @param [ [ Symbol | Hash<Symbol, [ Symbol | String ]> ]... ] *method_descriptors
|
28
28
|
# The methods to deprecate, with optional replacement instructions.
|
29
29
|
def deprecate(target_module, *method_descriptors)
|
30
|
-
Mongoid::Deprecation.
|
30
|
+
@_deprecator ||= Mongoid::Deprecation.new
|
31
|
+
@_deprecator.deprecate_methods(target_module, *method_descriptors)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
data/lib/mongoid/deprecation.rb
CHANGED
@@ -15,10 +15,10 @@ module Mongoid
|
|
15
15
|
#
|
16
16
|
# @return Array<Proc> The deprecation behavior.
|
17
17
|
def behavior
|
18
|
-
@behavior ||= Array(->(
|
18
|
+
@behavior ||= Array(->(*args) {
|
19
19
|
logger = Mongoid.logger
|
20
|
-
logger.warn(
|
21
|
-
logger.debug(
|
20
|
+
logger.warn(args[0])
|
21
|
+
logger.debug(args[1].join("\n ")) if debug
|
22
22
|
})
|
23
23
|
end
|
24
24
|
end
|
@@ -38,8 +38,12 @@ module Mongoid
|
|
38
38
|
consolidated = {}
|
39
39
|
each_pair do |key, value|
|
40
40
|
if key =~ /\$/
|
41
|
-
value.
|
42
|
-
value[
|
41
|
+
value.keys.each do |key2|
|
42
|
+
value2 = value[key2]
|
43
|
+
real_key = klass.database_field_name(key2)
|
44
|
+
|
45
|
+
value.delete(key2) if real_key != key2
|
46
|
+
value[real_key] = value_for(key, klass, real_key, value2)
|
43
47
|
end
|
44
48
|
consolidated[key] ||= {}
|
45
49
|
consolidated[key].update(value)
|
@@ -181,6 +185,24 @@ module Mongoid
|
|
181
185
|
|
182
186
|
private
|
183
187
|
|
188
|
+
# Get the value for the provided operator, klass, key and value.
|
189
|
+
#
|
190
|
+
# This is necessary for special cases like $rename, $addToSet and $push.
|
191
|
+
#
|
192
|
+
# @param [ String ] operator The operator.
|
193
|
+
# @param [ Class ] klass The model class.
|
194
|
+
# @param [ String | Symbol ] key The field key.
|
195
|
+
# @param [ Object ] value The original value.
|
196
|
+
#
|
197
|
+
# @return [ Object ] Value prepared for the provided operator.
|
198
|
+
def value_for(operator, klass, key, value)
|
199
|
+
case operator
|
200
|
+
when "$rename" then value.to_s
|
201
|
+
when "$addToSet", "$push" then value.mongoize
|
202
|
+
else mongoize_for(operator, klass, operator, value)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
184
206
|
# Mongoize for the klass, key and value.
|
185
207
|
#
|
186
208
|
# @api private
|
data/lib/mongoid/fields.rb
CHANGED
@@ -814,21 +814,19 @@ module Mongoid
|
|
814
814
|
#
|
815
815
|
# @api private
|
816
816
|
def retrieve_and_validate_type(name, type)
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
if
|
823
|
-
warn_message
|
824
|
-
|
825
|
-
|
826
|
-
else
|
827
|
-
warn_message += "Saving values of this type to the database will work as expected, however, querying them will return a value of the native Ruby Integer type."
|
828
|
-
end
|
829
|
-
Mongoid.logger.warn(warn_message)
|
817
|
+
result = TYPE_MAPPINGS[type] || unmapped_type(type)
|
818
|
+
raise Errors::InvalidFieldType.new(self, name, type) if !result.is_a?(Class)
|
819
|
+
|
820
|
+
if unsupported_type?(result)
|
821
|
+
warn_message = "Using #{result} as the field type is not supported. "
|
822
|
+
if result == BSON::Decimal128
|
823
|
+
warn_message += 'In BSON <= 4, the BSON::Decimal128 type will work as expected for both storing and querying, but will return a BigDecimal on query in BSON 5+. To use literal BSON::Decimal128 fields with BSON 5, set Mongoid.allow_bson5_decimal128 to true.'
|
824
|
+
else
|
825
|
+
warn_message += 'Saving values of this type to the database will work as expected, however, querying them will return a value of the native Ruby Integer type.'
|
830
826
|
end
|
827
|
+
Mongoid.logger.warn(warn_message)
|
831
828
|
end
|
829
|
+
|
832
830
|
result
|
833
831
|
end
|
834
832
|
|
@@ -847,6 +845,19 @@ module Mongoid
|
|
847
845
|
type || Object
|
848
846
|
end
|
849
847
|
end
|
848
|
+
|
849
|
+
# Queries whether or not the given type is permitted as a declared field
|
850
|
+
# type.
|
851
|
+
#
|
852
|
+
# @param [ Class ] type The type to query
|
853
|
+
#
|
854
|
+
# @return [ true | false ] whether or not the type is supported
|
855
|
+
#
|
856
|
+
# @api private
|
857
|
+
def unsupported_type?(type)
|
858
|
+
return !Mongoid::Config.allow_bson5_decimal128? if type == BSON::Decimal128
|
859
|
+
INVALID_BSON_CLASSES.include?(type)
|
860
|
+
end
|
850
861
|
end
|
851
862
|
end
|
852
863
|
end
|
@@ -43,6 +43,8 @@ module Mongoid
|
|
43
43
|
# @api private
|
44
44
|
define_model_callbacks :persist_parent
|
45
45
|
|
46
|
+
define_model_callbacks :commit, :rollback, only: :after
|
47
|
+
|
46
48
|
attr_accessor :before_callback_halted
|
47
49
|
end
|
48
50
|
|
@@ -140,6 +142,28 @@ module Mongoid
|
|
140
142
|
#
|
141
143
|
# @api private
|
142
144
|
def _mongoid_run_child_callbacks(kind, children: nil, &block)
|
145
|
+
if Mongoid::Config.around_callbacks_for_embeds
|
146
|
+
_mongoid_run_child_callbacks_with_around(kind, children: children, &block)
|
147
|
+
else
|
148
|
+
_mongoid_run_child_callbacks_without_around(kind, children: children, &block)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Execute the callbacks of given kind for embedded documents including
|
153
|
+
# around callbacks.
|
154
|
+
#
|
155
|
+
# @note This method is prone to stack overflow errors if the document
|
156
|
+
# has a large number of embedded documents. It is recommended to avoid
|
157
|
+
# using around callbacks for embedded documents until a proper solution
|
158
|
+
# is implemented.
|
159
|
+
#
|
160
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
161
|
+
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
162
|
+
# nil, callbacks will be executed on all cascadable children of
|
163
|
+
# the document.
|
164
|
+
#
|
165
|
+
# @api private
|
166
|
+
def _mongoid_run_child_callbacks_with_around(kind, children: nil, &block)
|
143
167
|
child, *tail = (children || cascadable_children(kind))
|
144
168
|
with_children = !Mongoid::Config.prevent_multiple_calls_of_embedded_callbacks
|
145
169
|
if child.nil?
|
@@ -148,23 +172,91 @@ module Mongoid
|
|
148
172
|
child.run_callbacks(child_callback_type(kind, child), with_children: with_children, &block)
|
149
173
|
else
|
150
174
|
child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do
|
151
|
-
|
175
|
+
_mongoid_run_child_callbacks_with_around(kind, children: tail, &block)
|
152
176
|
end
|
153
177
|
end
|
154
178
|
end
|
155
179
|
|
156
|
-
#
|
157
|
-
#
|
158
|
-
# associations are set on the document. This can also be used to delay
|
159
|
-
# applying the defaults on a document.
|
180
|
+
# Execute the callbacks of given kind for embedded documents without
|
181
|
+
# around callbacks.
|
160
182
|
#
|
161
|
-
# @
|
183
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
184
|
+
# @param [ Array<Document> ] children Children to execute callbacks on. If
|
185
|
+
# nil, callbacks will be executed on all cascadable children of
|
186
|
+
# the document.
|
187
|
+
#
|
188
|
+
# @api private
|
189
|
+
def _mongoid_run_child_callbacks_without_around(kind, children: nil, &block)
|
190
|
+
children = (children || cascadable_children(kind))
|
191
|
+
callback_list = _mongoid_run_child_before_callbacks(kind, children: children)
|
192
|
+
return false if callback_list == false
|
193
|
+
value = block&.call
|
194
|
+
callback_list.each do |_next_sequence, env|
|
195
|
+
env.value &&= value
|
196
|
+
end
|
197
|
+
return false if _mongoid_run_child_after_callbacks(callback_list: callback_list) == false
|
198
|
+
|
199
|
+
value
|
200
|
+
end
|
201
|
+
|
202
|
+
# Execute the before callbacks of given kind for embedded documents.
|
203
|
+
#
|
204
|
+
# @param [ Symbol ] kind The type of callback to execute.
|
205
|
+
# @param [ Array<Document> ] children Children to execute callbacks on.
|
206
|
+
# @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
|
207
|
+
# pairs of callback sequence and environment. This list will be later used
|
208
|
+
# to execute after callbacks in reverse order.
|
209
|
+
#
|
210
|
+
# @api private
|
211
|
+
def _mongoid_run_child_before_callbacks(kind, children: [], callback_list: [])
|
212
|
+
children.each do |child|
|
213
|
+
chain = child.__callbacks[child_callback_type(kind, child)]
|
214
|
+
env = ActiveSupport::Callbacks::Filters::Environment.new(child, false, nil)
|
215
|
+
next_sequence = compile_callbacks(chain)
|
216
|
+
unless next_sequence.final?
|
217
|
+
Mongoid.logger.warn("Around callbacks are disabled for embedded documents. Skipping around callbacks for #{child.class.name}.")
|
218
|
+
Mongoid.logger.warn("To enable around callbacks for embedded documents, set Mongoid::Config.around_callbacks_for_embeds to true.")
|
219
|
+
end
|
220
|
+
next_sequence.invoke_before(env)
|
221
|
+
return false if env.halted
|
222
|
+
env.value = !env.halted
|
223
|
+
callback_list << [next_sequence, env]
|
224
|
+
if (grandchildren = child.send(:cascadable_children, kind))
|
225
|
+
_mongoid_run_child_before_callbacks(kind, children: grandchildren, callback_list: callback_list)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
callback_list
|
229
|
+
end
|
230
|
+
|
231
|
+
# Execute the after callbacks.
|
232
|
+
#
|
233
|
+
# @param [ Array<ActiveSupport::Callbacks::CallbackSequence, ActiveSupport::Callbacks::Filters::Environment> ] callback_list List of
|
234
|
+
# pairs of callback sequence and environment.
|
235
|
+
def _mongoid_run_child_after_callbacks(callback_list: [])
|
236
|
+
callback_list.reverse_each do |next_sequence, env|
|
237
|
+
next_sequence.invoke_after(env)
|
238
|
+
return false if env.halted
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Returns the stored callbacks to be executed later.
|
243
|
+
#
|
244
|
+
# @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
|
162
245
|
#
|
163
246
|
# @api private
|
164
247
|
def pending_callbacks
|
165
248
|
@pending_callbacks ||= [].to_set
|
166
249
|
end
|
167
250
|
|
251
|
+
# Stores callbacks to be executed later. A good use case for
|
252
|
+
# this is delaying the after_find and after_initialize callbacks until the
|
253
|
+
# associations are set on the document. This can also be used to delay
|
254
|
+
# applying the defaults on a document.
|
255
|
+
#
|
256
|
+
# @param [ Array<Symbol> ] value Method symbols of the pending callbacks to store.
|
257
|
+
#
|
258
|
+
# @return [ Array<Symbol> ] Method symbols of the stored pending callbacks.
|
259
|
+
#
|
168
260
|
# @api private
|
169
261
|
def pending_callbacks=(value)
|
170
262
|
@pending_callbacks = value
|
@@ -299,7 +391,7 @@ module Mongoid
|
|
299
391
|
end
|
300
392
|
self.class.send :define_method, name do
|
301
393
|
env = ActiveSupport::Callbacks::Filters::Environment.new(self, false, nil)
|
302
|
-
sequence = chain
|
394
|
+
sequence = compile_callbacks(chain)
|
303
395
|
sequence.invoke_before(env)
|
304
396
|
env.value = !env.halted
|
305
397
|
sequence.invoke_after(env)
|
@@ -309,5 +401,24 @@ module Mongoid
|
|
309
401
|
end
|
310
402
|
send(name)
|
311
403
|
end
|
404
|
+
|
405
|
+
# Compile the callback chain.
|
406
|
+
#
|
407
|
+
# This method hides the differences between ActiveSupport implementations
|
408
|
+
# before and after 7.1.
|
409
|
+
#
|
410
|
+
# @param [ ActiveSupport::Callbacks::CallbackChain ] chain The callback chain.
|
411
|
+
# @param [ Symbol | nil ] type The type of callback chain to compile.
|
412
|
+
#
|
413
|
+
# @return [ ActiveSupport::Callbacks::CallbackSequence ] The compiled callback sequence.
|
414
|
+
def compile_callbacks(chain, type = nil)
|
415
|
+
if chain.method(:compile).arity == 0
|
416
|
+
# ActiveSupport < 7.1
|
417
|
+
chain.compile
|
418
|
+
else
|
419
|
+
# ActiveSupport >= 7.1
|
420
|
+
chain.compile(type)
|
421
|
+
end
|
422
|
+
end
|
312
423
|
end
|
313
424
|
end
|
data/lib/mongoid/version.rb
CHANGED
@@ -557,6 +557,7 @@ describe 'callbacks integration tests' do
|
|
557
557
|
|
558
558
|
context 'nested embedded documents' do
|
559
559
|
config_override :prevent_multiple_calls_of_embedded_callbacks, true
|
560
|
+
config_override :around_callbacks_for_embeds, true
|
560
561
|
|
561
562
|
let(:logger) { Array.new }
|
562
563
|
|
@@ -581,4 +582,24 @@ describe 'callbacks integration tests' do
|
|
581
582
|
expect(logger).to eq(%i[embedded_twice embedded_once root])
|
582
583
|
end
|
583
584
|
end
|
585
|
+
|
586
|
+
context 'cascade callbacks' do
|
587
|
+
ruby_version_gte '3.0'
|
588
|
+
config_override :around_callbacks_for_embeds, false
|
589
|
+
|
590
|
+
let(:book) do
|
591
|
+
Book.new
|
592
|
+
end
|
593
|
+
|
594
|
+
before do
|
595
|
+
1500.times do
|
596
|
+
book.pages.build
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
# https://jira.mongodb.org/browse/MONGOID-5658
|
601
|
+
it 'does not raise SystemStackError' do
|
602
|
+
expect { book.save! }.not_to raise_error(SystemStackError)
|
603
|
+
end
|
604
|
+
end
|
584
605
|
end
|
@@ -2708,4 +2708,31 @@ describe Mongoid::Attributes do
|
|
2708
2708
|
catalog.set_field.should == Set.new([ 1, 2 ])
|
2709
2709
|
end
|
2710
2710
|
end
|
2711
|
+
|
2712
|
+
context 'when an embedded field has a capitalized store_as name' do
|
2713
|
+
let(:person) { Person.new(Purse: { brand: 'Gucci' }) }
|
2714
|
+
|
2715
|
+
it 'sets the value' do
|
2716
|
+
expect(person.purse.brand).to eq('Gucci')
|
2717
|
+
end
|
2718
|
+
|
2719
|
+
it 'saves successfully' do
|
2720
|
+
expect(person.save!).to eq(true)
|
2721
|
+
end
|
2722
|
+
|
2723
|
+
context 'when persisted' do
|
2724
|
+
before do
|
2725
|
+
person.save!
|
2726
|
+
person.reload
|
2727
|
+
end
|
2728
|
+
|
2729
|
+
it 'persists the value' do
|
2730
|
+
expect(person.reload.purse.brand).to eq('Gucci')
|
2731
|
+
end
|
2732
|
+
|
2733
|
+
it 'uses the correct key in the database' do
|
2734
|
+
expect(person.collection.find(_id: person.id).first['Purse']['_id']).to eq(person.purse.id)
|
2735
|
+
end
|
2736
|
+
end
|
2737
|
+
end
|
2711
2738
|
end
|
data/spec/mongoid/config_spec.rb
CHANGED
@@ -345,6 +345,15 @@ describe Mongoid::Config do
|
|
345
345
|
it_behaves_like "a config option"
|
346
346
|
end
|
347
347
|
|
348
|
+
context 'when setting the allow_bson5_decimal128 option in the config' do
|
349
|
+
min_bson_version '5.0'
|
350
|
+
|
351
|
+
let(:option) { :allow_bson5_decimal128 }
|
352
|
+
let(:default) { false }
|
353
|
+
|
354
|
+
it_behaves_like "a config option"
|
355
|
+
end
|
356
|
+
|
348
357
|
context 'when setting the broken_updates option in the config' do
|
349
358
|
let(:option) { :broken_updates }
|
350
359
|
let(:default) { false }
|