mongoid 7.2.3 → 7.3.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.tar.gz.sig +0 -0
- data/Rakefile +16 -0
- data/lib/config/locales/en.yml +2 -2
- data/lib/mongoid/association/accessors.rb +1 -1
- data/lib/mongoid/association/constrainable.rb +1 -1
- data/lib/mongoid/association/depending.rb +4 -4
- data/lib/mongoid/association/embedded/batchable.rb +1 -1
- data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
- data/lib/mongoid/association/nested/many.rb +1 -1
- data/lib/mongoid/association/nested/one.rb +4 -2
- data/lib/mongoid/association/proxy.rb +6 -1
- data/lib/mongoid/association/referenced/auto_save.rb +2 -2
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
- data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
- data/lib/mongoid/attributes.rb +24 -13
- data/lib/mongoid/attributes/projector.rb +120 -0
- data/lib/mongoid/cacheable.rb +2 -2
- data/lib/mongoid/clients.rb +1 -1
- data/lib/mongoid/clients/factory.rb +22 -8
- data/lib/mongoid/config.rb +19 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
- data/lib/mongoid/copyable.rb +1 -1
- data/lib/mongoid/criteria.rb +4 -5
- data/lib/mongoid/criteria/findable.rb +1 -1
- data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
- data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
- data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
- data/lib/mongoid/document.rb +1 -15
- data/lib/mongoid/errors/delete_restriction.rb +8 -9
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions/boolean.rb +1 -2
- data/lib/mongoid/extensions/false_class.rb +1 -1
- data/lib/mongoid/extensions/hash.rb +2 -2
- data/lib/mongoid/extensions/true_class.rb +1 -1
- data/lib/mongoid/fields.rb +43 -5
- data/lib/mongoid/inspectable.rb +1 -1
- data/lib/mongoid/matcher.rb +7 -0
- data/lib/mongoid/matcher/bits.rb +41 -0
- data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_all_set.rb +20 -0
- data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_any_set.rb +20 -0
- data/lib/mongoid/matcher/expression.rb +4 -0
- data/lib/mongoid/matcher/field_operator.rb +6 -0
- data/lib/mongoid/matcher/mod.rb +17 -0
- data/lib/mongoid/matcher/type.rb +99 -0
- data/lib/mongoid/persistable/deletable.rb +1 -2
- data/lib/mongoid/persistable/destroyable.rb +8 -2
- data/lib/mongoid/persistable/updatable.rb +27 -2
- data/lib/mongoid/query_cache.rb +35 -29
- data/lib/mongoid/selectable.rb +5 -7
- data/lib/mongoid/shardable.rb +21 -5
- data/lib/mongoid/touchable.rb +23 -4
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/associations/embeds_many_spec.rb +44 -0
- data/spec/integration/associations/has_one_spec.rb +48 -0
- data/spec/integration/criteria/date_field_spec.rb +1 -1
- data/spec/integration/document_spec.rb +9 -0
- data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
- data/spec/integration/matcher_operator_data/comment.yml +22 -0
- data/spec/integration/matcher_operator_data/in.yml +16 -0
- data/spec/integration/matcher_operator_data/mod.yml +55 -0
- data/spec/integration/matcher_operator_data/type.yml +70 -0
- data/spec/integration/matcher_operator_data/type_array.yml +16 -0
- data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
- data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
- data/spec/integration/matcher_operator_data/type_code.yml +26 -0
- data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
- data/spec/integration/matcher_operator_data/type_date.yml +39 -0
- data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
- data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
- data/spec/integration/matcher_operator_data/type_double.yml +15 -0
- data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
- data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
- data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_null.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
- data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
- data/spec/integration/matcher_operator_data/type_string.yml +15 -0
- data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
- data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
- data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
- data/spec/lite_spec_helper.rb +2 -0
- data/spec/mongoid/association/depending_spec.rb +391 -352
- data/spec/mongoid/association/nested/one_spec.rb +18 -14
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
- data/spec/mongoid/atomic/paths_spec.rb +64 -12
- data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
- data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
- data/spec/mongoid/attributes/projector_spec.rb +41 -0
- data/spec/mongoid/attributes_spec.rb +98 -6
- data/spec/mongoid/clients/factory_spec.rb +48 -0
- data/spec/mongoid/config_spec.rb +32 -0
- data/spec/mongoid/contextual/mongo_spec.rb +2 -2
- data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
- data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
- data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
- data/spec/mongoid/criteria_projection_spec.rb +411 -0
- data/spec/mongoid/criteria_spec.rb +0 -275
- data/spec/mongoid/document_spec.rb +13 -13
- data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
- data/spec/mongoid/extensions/false_class_spec.rb +1 -1
- data/spec/mongoid/extensions/string_spec.rb +5 -5
- data/spec/mongoid/extensions/true_class_spec.rb +1 -1
- data/spec/mongoid/fields/localized_spec.rb +4 -4
- data/spec/mongoid/fields_spec.rb +4 -4
- data/spec/mongoid/inspectable_spec.rb +12 -4
- data/spec/mongoid/persistable/deletable_spec.rb +175 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
- data/spec/mongoid/persistable/savable_spec.rb +3 -5
- data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
- data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
- data/spec/mongoid/reloadable_spec.rb +18 -1
- data/spec/mongoid/shardable_spec.rb +44 -0
- data/spec/mongoid/touchable_spec.rb +104 -16
- data/spec/mongoid/touchable_spec_models.rb +52 -0
- data/spec/mongoid/validatable_spec.rb +1 -1
- data/spec/spec_helper.rb +6 -2
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/models/bolt.rb +8 -0
- data/spec/support/models/hole.rb +13 -0
- data/spec/support/models/mop.rb +0 -1
- data/spec/support/models/nut.rb +8 -0
- data/spec/support/models/person.rb +6 -0
- data/spec/support/models/sealer.rb +8 -0
- data/spec/support/models/shirt.rb +12 -0
- data/spec/support/models/spacer.rb +8 -0
- data/spec/support/models/threadlocker.rb +8 -0
- data/spec/support/models/washer.rb +8 -0
- metadata +97 -3
- metadata.gz.sig +5 -3
- data/spec/support/cluster_config.rb +0 -158
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAllSet
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.all? do |c|
|
|
11
|
+
value & (1<<c) > 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition == condition
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAnyClear
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.any? do |c|
|
|
11
|
+
value & (1<<c) == 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition < condition
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAnySet
|
|
6
|
+
include Bits
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def array_matches?(value, condition)
|
|
10
|
+
condition.any? do |c|
|
|
11
|
+
value & (1<<c) > 0
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def int_matches?(value, condition)
|
|
16
|
+
value & condition > 0
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -5,6 +5,10 @@ module Mongoid
|
|
|
5
5
|
module FieldOperator
|
|
6
6
|
MAP = {
|
|
7
7
|
'$all' => All,
|
|
8
|
+
'$bitsAllClear' => BitsAllClear,
|
|
9
|
+
'$bitsAllSet' => BitsAllSet,
|
|
10
|
+
'$bitsAnyClear' => BitsAnyClear,
|
|
11
|
+
'$bitsAnySet' => BitsAnySet,
|
|
8
12
|
'$elemMatch' => ElemMatch,
|
|
9
13
|
'$eq' => Eq,
|
|
10
14
|
'$exists' => Exists,
|
|
@@ -13,11 +17,13 @@ module Mongoid
|
|
|
13
17
|
'$in' => In,
|
|
14
18
|
'$lt' => Lt,
|
|
15
19
|
'$lte' => Lte,
|
|
20
|
+
'$mod' => Mod,
|
|
16
21
|
'$nin' => Nin,
|
|
17
22
|
'$ne' => Ne,
|
|
18
23
|
'$not' => Not,
|
|
19
24
|
'$regex' => Regex,
|
|
20
25
|
'$size' => Size,
|
|
26
|
+
'$type' => Type,
|
|
21
27
|
}.freeze
|
|
22
28
|
|
|
23
29
|
module_function def get(op)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module Mod
|
|
6
|
+
module_function def matches?(exists, value, condition)
|
|
7
|
+
unless Array === condition
|
|
8
|
+
raise Errors::InvalidQuery, "Unknown $mod argument #{condition}"
|
|
9
|
+
end
|
|
10
|
+
if condition.length != 2
|
|
11
|
+
raise Errors::InvalidQuery, "Malformed $mod argument #{condition}, should have 2 elements"
|
|
12
|
+
end
|
|
13
|
+
condition[1] == value%condition[0]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @see https://docs.mongodb.com/manual/reference/operator/query/type/
|
|
5
|
+
#
|
|
6
|
+
# @api private
|
|
7
|
+
module Type
|
|
8
|
+
module_function def matches?(exists, value, condition)
|
|
9
|
+
conditions = case condition
|
|
10
|
+
when Array
|
|
11
|
+
condition
|
|
12
|
+
when Integer
|
|
13
|
+
[condition]
|
|
14
|
+
else
|
|
15
|
+
raise Errors::InvalidQuery, "Unknown $type argument: #{condition}"
|
|
16
|
+
end
|
|
17
|
+
conditions.each do |condition|
|
|
18
|
+
if one_matches?(exists, value, condition)
|
|
19
|
+
return true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module_function def one_matches?(exists, value, condition)
|
|
26
|
+
case condition
|
|
27
|
+
when 1
|
|
28
|
+
# Double
|
|
29
|
+
Float === value
|
|
30
|
+
when 2
|
|
31
|
+
# String
|
|
32
|
+
String === value
|
|
33
|
+
when 3
|
|
34
|
+
# Object
|
|
35
|
+
Hash === value
|
|
36
|
+
when 4
|
|
37
|
+
# Array
|
|
38
|
+
Array === value
|
|
39
|
+
when 5
|
|
40
|
+
# Binary data
|
|
41
|
+
BSON::Binary === value
|
|
42
|
+
when 6
|
|
43
|
+
# Undefined
|
|
44
|
+
BSON::Undefined === value
|
|
45
|
+
when 7
|
|
46
|
+
# ObjectId
|
|
47
|
+
BSON::ObjectId === value
|
|
48
|
+
when 8
|
|
49
|
+
# Boolean
|
|
50
|
+
TrueClass === value || FalseClass === value
|
|
51
|
+
when 9
|
|
52
|
+
# Date
|
|
53
|
+
Date === value || Time === value || DateTime === value
|
|
54
|
+
when 10
|
|
55
|
+
# Null
|
|
56
|
+
exists && NilClass === value
|
|
57
|
+
when 11
|
|
58
|
+
# Regex
|
|
59
|
+
Regexp::Raw === value || ::Regexp === value
|
|
60
|
+
when 12
|
|
61
|
+
# DBPointer deprecated
|
|
62
|
+
BSON::DbPointer === value
|
|
63
|
+
when 13
|
|
64
|
+
# JavaScript
|
|
65
|
+
BSON::Code === value
|
|
66
|
+
when 14
|
|
67
|
+
# Symbol deprecated
|
|
68
|
+
Symbol === value || BSON::Symbol::Raw === value
|
|
69
|
+
when 15
|
|
70
|
+
# Javascript with code deprecated
|
|
71
|
+
BSON::CodeWithScope === value
|
|
72
|
+
when 16
|
|
73
|
+
# 32-bit int
|
|
74
|
+
BSON::Int32 === value || Integer === value && (-2**32..2**32-1).include?(value)
|
|
75
|
+
when 17
|
|
76
|
+
# Timestamp
|
|
77
|
+
BSON::Timestamp === value
|
|
78
|
+
when 18
|
|
79
|
+
# Long
|
|
80
|
+
BSON::Int64 === value ||
|
|
81
|
+
Integer === value &&
|
|
82
|
+
(-2**64..2**64-1).include?(value) &&
|
|
83
|
+
!(-2**32..2**32-1).include?(value)
|
|
84
|
+
when 19
|
|
85
|
+
# Decimal
|
|
86
|
+
BSON::Decimal128 === value
|
|
87
|
+
when -1
|
|
88
|
+
# minKey
|
|
89
|
+
BSON::MinKey === value
|
|
90
|
+
when 127
|
|
91
|
+
# maxKey
|
|
92
|
+
BSON::MaxKey === value
|
|
93
|
+
else
|
|
94
|
+
raise Errors::InvalidQuery, "Unknown $type argument: #{condition}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -47,7 +47,7 @@ module Mongoid
|
|
|
47
47
|
#
|
|
48
48
|
# @since 4.0.0
|
|
49
49
|
def atomic_deletes
|
|
50
|
-
{ atomic_delete_modifier => { atomic_path => _index ? { "_id" =>
|
|
50
|
+
{ atomic_delete_modifier => { atomic_path => _index ? { "_id" => _id } : true }}
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Delete the embedded document.
|
|
@@ -117,7 +117,6 @@ module Mongoid
|
|
|
117
117
|
#
|
|
118
118
|
# @since 4.0.0
|
|
119
119
|
def prepare_delete
|
|
120
|
-
return false unless catch(:abort) { apply_delete_dependencies! }
|
|
121
120
|
yield(self)
|
|
122
121
|
freeze
|
|
123
122
|
self.destroyed = true
|
|
@@ -23,13 +23,19 @@ module Mongoid
|
|
|
23
23
|
def destroy(options = nil)
|
|
24
24
|
raise Errors::ReadonlyDocument.new(self.class) if readonly?
|
|
25
25
|
self.flagged_for_destroy = true
|
|
26
|
-
result = run_callbacks(:destroy)
|
|
26
|
+
result = run_callbacks(:destroy) do
|
|
27
|
+
if catch(:abort) { apply_destroy_dependencies! }
|
|
28
|
+
delete(options || {})
|
|
29
|
+
else
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
27
33
|
self.flagged_for_destroy = false
|
|
28
34
|
result
|
|
29
35
|
end
|
|
30
36
|
|
|
31
37
|
def destroy!(options = {})
|
|
32
|
-
destroy || raise(Errors::DocumentNotDestroyed.new(
|
|
38
|
+
destroy || raise(Errors::DocumentNotDestroyed.new(_id, self.class))
|
|
33
39
|
end
|
|
34
40
|
|
|
35
41
|
module ClassMethods
|
|
@@ -137,8 +137,33 @@ module Mongoid
|
|
|
137
137
|
coll = collection(_root)
|
|
138
138
|
selector = atomic_selector
|
|
139
139
|
coll.find(selector).update_one(positionally(selector, updates), session: _session)
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
|
|
141
|
+
# The following code applies updates which would cause
|
|
142
|
+
# path conflicts in MongoDB, for example when changing attributes
|
|
143
|
+
# of foo.0.bars while adding another foo. Each conflicting update
|
|
144
|
+
# is applied using its own write.
|
|
145
|
+
#
|
|
146
|
+
# TODO: MONGOID-5026: reduce the number of writes performed by
|
|
147
|
+
# more intelligently combining the writes such that there are
|
|
148
|
+
# fewer conflicts.
|
|
149
|
+
conflicts.each_pair do |modifier, changes|
|
|
150
|
+
|
|
151
|
+
# Group the changes according to their root key which is
|
|
152
|
+
# the top-level association name.
|
|
153
|
+
# This handles at least the cases described in MONGOID-4982.
|
|
154
|
+
conflicting_change_groups = changes.group_by do |key, _|
|
|
155
|
+
key.split(".", 2).first
|
|
156
|
+
end.values
|
|
157
|
+
|
|
158
|
+
# Apply changes in batches. Pop one change from each
|
|
159
|
+
# field-conflict group round-robin until all changes
|
|
160
|
+
# have been applied.
|
|
161
|
+
while batched_changes = conflicting_change_groups.map(&:pop).compact.to_h.presence
|
|
162
|
+
coll.find(selector).update_one(
|
|
163
|
+
positionally(selector, modifier => batched_changes),
|
|
164
|
+
session: _session,
|
|
165
|
+
)
|
|
166
|
+
end
|
|
142
167
|
end
|
|
143
168
|
end
|
|
144
169
|
end
|
data/lib/mongoid/query_cache.rb
CHANGED
|
@@ -117,38 +117,44 @@ module Mongoid
|
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
# Instantiate the middleware.
|
|
127
|
-
#
|
|
128
|
-
# @example Create the new middleware.
|
|
129
|
-
# Middleware.new(app)
|
|
130
|
-
#
|
|
131
|
-
# @param [ Object ] app The rack applciation stack.
|
|
120
|
+
if defined?(Mongo::QueryCache::Middleware)
|
|
121
|
+
Middleware = Mongo::QueryCache::Middleware
|
|
122
|
+
else
|
|
123
|
+
# The middleware to be added to a rack application in order to activate the
|
|
124
|
+
# query cache.
|
|
132
125
|
#
|
|
133
126
|
# @since 4.0.0
|
|
134
|
-
|
|
135
|
-
@app = app
|
|
136
|
-
end
|
|
127
|
+
class Middleware
|
|
137
128
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
129
|
+
# Instantiate the middleware.
|
|
130
|
+
#
|
|
131
|
+
# @example Create the new middleware.
|
|
132
|
+
# Middleware.new(app)
|
|
133
|
+
#
|
|
134
|
+
# @param [ Object ] app The rack application stack.
|
|
135
|
+
#
|
|
136
|
+
# @since 4.0.0
|
|
137
|
+
def initialize(app)
|
|
138
|
+
@app = app
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Execute the request, wrapping in a query cache.
|
|
142
|
+
#
|
|
143
|
+
# @example Execute the request.
|
|
144
|
+
# middleware.call(env)
|
|
145
|
+
#
|
|
146
|
+
# @param [ Object ] env The environment.
|
|
147
|
+
#
|
|
148
|
+
# @return [ Object ] The result of the call.
|
|
149
|
+
#
|
|
150
|
+
# @since 4.0.0
|
|
151
|
+
def call(env)
|
|
152
|
+
QueryCache.cache do
|
|
153
|
+
@app.call(env)
|
|
154
|
+
end
|
|
155
|
+
ensure
|
|
156
|
+
QueryCache.clear_cache
|
|
157
|
+
end
|
|
152
158
|
end
|
|
153
159
|
end
|
|
154
160
|
|
data/lib/mongoid/selectable.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Mongoid
|
|
|
21
21
|
# @since 1.0.0
|
|
22
22
|
def atomic_selector
|
|
23
23
|
@atomic_selector ||=
|
|
24
|
-
(embedded? ? embedded_atomic_selector :
|
|
24
|
+
(embedded? ? embedded_atomic_selector : root_atomic_selector_in_db)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
private
|
|
@@ -44,18 +44,16 @@ module Mongoid
|
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
# Get the atomic selector
|
|
47
|
+
# Get the atomic selector that would match the existing version of the
|
|
48
|
+
# root document.
|
|
48
49
|
#
|
|
49
50
|
# @api private
|
|
50
51
|
#
|
|
51
|
-
# @example Get the root atomic selector.
|
|
52
|
-
# document.root_atomic_selector
|
|
53
|
-
#
|
|
54
52
|
# @return [ Hash ] The root document selector.
|
|
55
53
|
#
|
|
56
54
|
# @since 4.0.0
|
|
57
|
-
def
|
|
58
|
-
{ "_id" => _id }.merge!(
|
|
55
|
+
def root_atomic_selector_in_db
|
|
56
|
+
{ "_id" => _id }.merge!(shard_key_selector_in_db)
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
end
|
data/lib/mongoid/shardable.rb
CHANGED
|
@@ -52,15 +52,31 @@ module Mongoid
|
|
|
52
52
|
self.class.shard_key_fields
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
# @example Get the selector for the shard keys.
|
|
58
|
-
# person.shard_key_selector
|
|
55
|
+
# Returns the selector that would match the current version of this
|
|
56
|
+
# document.
|
|
59
57
|
#
|
|
60
58
|
# @return [ Hash ] The shard key selector.
|
|
61
59
|
#
|
|
62
|
-
# @
|
|
60
|
+
# @api private
|
|
63
61
|
def shard_key_selector
|
|
62
|
+
selector = {}
|
|
63
|
+
shard_key_fields.each do |field|
|
|
64
|
+
selector[field.to_s] = send(field)
|
|
65
|
+
end
|
|
66
|
+
selector
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns the selector that would match the existing version of this
|
|
70
|
+
# document in the database.
|
|
71
|
+
#
|
|
72
|
+
# If the document is not persisted, this method uses the current values
|
|
73
|
+
# of the shard key fields. If the document is persisted, this method
|
|
74
|
+
# uses the values retrieved from the database.
|
|
75
|
+
#
|
|
76
|
+
# @return [ Hash ] The shard key selector.
|
|
77
|
+
#
|
|
78
|
+
# @api private
|
|
79
|
+
def shard_key_selector_in_db
|
|
64
80
|
selector = {}
|
|
65
81
|
shard_key_fields.each do |field|
|
|
66
82
|
selector[field.to_s] = new_record? ? send(field) : attribute_was(field)
|
data/lib/mongoid/touchable.rb
CHANGED
|
@@ -30,11 +30,30 @@ module Mongoid
|
|
|
30
30
|
write_attribute(:updated_at, current) if respond_to?("updated_at=")
|
|
31
31
|
write_attribute(field, current) if field
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
# If the document being touched is embedded, touch its parents
|
|
34
|
+
# all the way through the composition hierarchy to the root object,
|
|
35
|
+
# because when an embedded document is changed the write is actually
|
|
36
|
+
# performed by the composition root. See MONGOID-3468.
|
|
37
|
+
if _parent
|
|
38
|
+
# This will persist updated_at on this document as well as parents.
|
|
39
|
+
# TODO support passing the field name to the parent's touch method;
|
|
40
|
+
# I believe it should be read out of
|
|
41
|
+
# _association.inverse_association.options but inverse_association
|
|
42
|
+
# seems to not always/ever be set here. See MONGOID-5014.
|
|
43
|
+
_parent.touch
|
|
44
|
+
else
|
|
45
|
+
# If the current document is not embedded, it is composition root
|
|
46
|
+
# and we need to persist the write here.
|
|
47
|
+
touches = touch_atomic_updates(field)
|
|
48
|
+
unless touches["$set"].blank?
|
|
49
|
+
selector = atomic_selector
|
|
50
|
+
_root.collection.find(selector).update_one(positionally(selector, touches), session: _session)
|
|
51
|
+
end
|
|
37
52
|
end
|
|
53
|
+
|
|
54
|
+
# Callbacks are invoked on the composition root first and on the
|
|
55
|
+
# leaf-most embedded document last.
|
|
56
|
+
# TODO add tests, see MONGOID-5015.
|
|
38
57
|
run_callbacks(:touch)
|
|
39
58
|
true
|
|
40
59
|
end
|