mongoid 7.2.6 → 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/README.md +1 -1
- data/Rakefile +16 -0
- data/lib/config/locales/en.yml +2 -15
- 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 +11 -4
- data/lib/mongoid/association/nested/many.rb +1 -1
- data/lib/mongoid/association/nested/one.rb +4 -2
- data/lib/mongoid/association/proxy.rb +7 -2
- 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 +3 -3
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
- data/lib/mongoid/association/relatable.rb +0 -2
- data/lib/mongoid/attributes/projector.rb +120 -0
- data/lib/mongoid/attributes.rb +24 -13
- data/lib/mongoid/cacheable.rb +2 -2
- data/lib/mongoid/clients/factory.rb +22 -8
- data/lib/mongoid/clients.rb +1 -1
- data/lib/mongoid/config/environment.rb +1 -9
- data/lib/mongoid/config.rb +19 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
- data/lib/mongoid/contextual/atomic.rb +2 -7
- data/lib/mongoid/contextual/none.rb +0 -3
- data/lib/mongoid/copyable.rb +1 -1
- data/lib/mongoid/criteria/findable.rb +1 -1
- data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
- data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
- data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
- data/lib/mongoid/criteria/queryable/selectable.rb +10 -10
- data/lib/mongoid/criteria/queryable/storable.rb +4 -4
- data/lib/mongoid/criteria.rb +5 -6
- data/lib/mongoid/document.rb +3 -18
- data/lib/mongoid/errors/delete_restriction.rb +8 -9
- data/lib/mongoid/errors/mongoid_error.rb +1 -1
- data/lib/mongoid/errors.rb +0 -2
- 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/interceptable.rb +1 -1
- 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/matcher.rb +7 -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/persistence_context.rb +1 -3
- data/lib/mongoid/query_cache.rb +36 -40
- data/lib/mongoid/selectable.rb +5 -7
- data/lib/mongoid/shardable.rb +21 -5
- data/lib/mongoid/tasks/database.rb +1 -1
- data/lib/mongoid/touchable.rb +23 -4
- data/lib/mongoid/validatable/associated.rb +1 -1
- data/lib/mongoid/validatable/presence.rb +3 -3
- data/lib/mongoid/validatable/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid.rb +0 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
- data/spec/integration/app_spec.rb +0 -3
- 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/integration/stringified_symbol_field_spec.rb +2 -2
- data/spec/lite_spec_helper.rb +2 -0
- data/spec/mongoid/association/depending_spec.rb +391 -352
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +4 -17
- data/spec/mongoid/association/nested/one_spec.rb +18 -14
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -25
- data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +0 -20
- 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_many_models.rb +0 -17
- 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 +51 -9
- data/spec/mongoid/clients/options_spec.rb +3 -11
- data/spec/mongoid/config/environment_spec.rb +8 -86
- data/spec/mongoid/config_spec.rb +32 -0
- data/spec/mongoid/contextual/atomic_spec.rb +25 -64
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -1
- 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 -279
- data/spec/mongoid/document_query_spec.rb +0 -51
- data/spec/mongoid/document_spec.rb +14 -34
- data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
- data/spec/mongoid/errors/mongoid_error_spec.rb +8 -20
- 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/updatable_spec.rb +0 -2
- data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
- data/spec/mongoid/persistable_spec.rb +2 -2
- data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
- data/spec/mongoid/query_cache_spec.rb +0 -24
- 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/shared/lib/mrss/cluster_config.rb +3 -8
- data/spec/shared/lib/mrss/constraints.rb +10 -41
- data/spec/shared/lib/mrss/docker_runner.rb +1 -7
- data/spec/shared/lib/mrss/server_version_registry.rb +12 -17
- data/spec/shared/lib/mrss/spec_organizer.rb +1 -18
- data/spec/shared/share/Dockerfile.erb +33 -125
- data/spec/shared/shlib/server.sh +23 -100
- data/spec/shared/shlib/set_env.sh +1 -4
- data/spec/spec_helper.rb +7 -3
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/models/address.rb +0 -4
- 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 -9
- 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
- data.tar.gz.sig +0 -0
- metadata +609 -545
- metadata.gz.sig +0 -0
- data/lib/mongoid/errors/empty_config_file.rb +0 -26
- data/lib/mongoid/errors/invalid_config_file.rb +0 -26
- data/spec/integration/contextual/empty_spec.rb +0 -142
- data/spec/mongoid/errors/invalid_config_file_spec.rb +0 -32
- data/spec/shared/bin/s3-copy +0 -45
- data/spec/shared/bin/s3-upload +0 -69
- data/spec/shared/lib/mrss/event_subscriber.rb +0 -200
- data/spec/shared/share/haproxy-1.conf +0 -16
- data/spec/shared/share/haproxy-2.conf +0 -17
- data/spec/support/cluster_config.rb +0 -158
data/lib/mongoid/matcher.rb
CHANGED
|
@@ -79,6 +79,11 @@ end
|
|
|
79
79
|
|
|
80
80
|
require 'mongoid/matcher/all'
|
|
81
81
|
require 'mongoid/matcher/and'
|
|
82
|
+
require 'mongoid/matcher/bits'
|
|
83
|
+
require 'mongoid/matcher/bits_all_clear'
|
|
84
|
+
require 'mongoid/matcher/bits_all_set'
|
|
85
|
+
require 'mongoid/matcher/bits_any_clear'
|
|
86
|
+
require 'mongoid/matcher/bits_any_set'
|
|
82
87
|
require 'mongoid/matcher/elem_match'
|
|
83
88
|
require 'mongoid/matcher/elem_match_expression'
|
|
84
89
|
require 'mongoid/matcher/eq'
|
|
@@ -92,6 +97,7 @@ require 'mongoid/matcher/gte'
|
|
|
92
97
|
require 'mongoid/matcher/in'
|
|
93
98
|
require 'mongoid/matcher/lt'
|
|
94
99
|
require 'mongoid/matcher/lte'
|
|
100
|
+
require 'mongoid/matcher/mod'
|
|
95
101
|
require 'mongoid/matcher/ne'
|
|
96
102
|
require 'mongoid/matcher/nin'
|
|
97
103
|
require 'mongoid/matcher/nor'
|
|
@@ -99,5 +105,6 @@ require 'mongoid/matcher/not'
|
|
|
99
105
|
require 'mongoid/matcher/or'
|
|
100
106
|
require 'mongoid/matcher/regex'
|
|
101
107
|
require 'mongoid/matcher/size'
|
|
108
|
+
require 'mongoid/matcher/type'
|
|
102
109
|
require 'mongoid/matcher/expression_operator'
|
|
103
110
|
require 'mongoid/matcher/field_operator'
|
|
@@ -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
|
|
@@ -237,9 +237,7 @@ module Mongoid
|
|
|
237
237
|
# @since 6.0.0
|
|
238
238
|
def clear(object, cluster = nil, original_context = nil)
|
|
239
239
|
if context = get(object)
|
|
240
|
-
|
|
241
|
-
context.client.close
|
|
242
|
-
end
|
|
240
|
+
context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
|
|
243
241
|
end
|
|
244
242
|
ensure
|
|
245
243
|
Thread.current["[mongoid][#{object.object_id}]:context"] = original_context
|
data/lib/mongoid/query_cache.rb
CHANGED
|
@@ -7,14 +7,8 @@ module Mongoid
|
|
|
7
7
|
#
|
|
8
8
|
# @since 4.0.0
|
|
9
9
|
module QueryCache
|
|
10
|
-
# @api private
|
|
11
|
-
LEGACY_WARNING = <<~DOC
|
|
12
|
-
You are using the legacy Mongoid query cache which has known issues.
|
|
13
|
-
Please upgrade the `mongo' gem to at least 2.14.0 to use the improved driver query cache.
|
|
14
|
-
Refer to: https://docs.mongodb.com/mongoid/current/tutorials/mongoid-queries/#the-improved-driver-query-cache
|
|
15
|
-
DOC
|
|
16
|
-
|
|
17
10
|
class << self
|
|
11
|
+
|
|
18
12
|
# Get the cached queries.
|
|
19
13
|
#
|
|
20
14
|
# @example Get the cached queries from the current thread.
|
|
@@ -92,10 +86,6 @@ module Mongoid
|
|
|
92
86
|
if defined?(Mongo::QueryCache)
|
|
93
87
|
Mongo::QueryCache.cache(&block)
|
|
94
88
|
else
|
|
95
|
-
@legacy_query_cache_warned ||= begin
|
|
96
|
-
Mongoid.logger.warn(LEGACY_WARNING)
|
|
97
|
-
true
|
|
98
|
-
end
|
|
99
89
|
enabled = QueryCache.enabled?
|
|
100
90
|
QueryCache.enabled = true
|
|
101
91
|
begin
|
|
@@ -127,38 +117,44 @@ module Mongoid
|
|
|
127
117
|
end
|
|
128
118
|
end
|
|
129
119
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# Instantiate the middleware.
|
|
137
|
-
#
|
|
138
|
-
# @example Create the new middleware.
|
|
139
|
-
# Middleware.new(app)
|
|
140
|
-
#
|
|
141
|
-
# @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.
|
|
142
125
|
#
|
|
143
126
|
# @since 4.0.0
|
|
144
|
-
|
|
145
|
-
@app = app
|
|
146
|
-
end
|
|
127
|
+
class Middleware
|
|
147
128
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
|
162
158
|
end
|
|
163
159
|
end
|
|
164
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)
|
|
@@ -123,7 +123,7 @@ module Mongoid
|
|
|
123
123
|
next if model.shard_config.nil?
|
|
124
124
|
|
|
125
125
|
if model.embedded? && !model.cyclic?
|
|
126
|
-
logger.warn("MONGOID: #{model} has shard config but is
|
|
126
|
+
logger.warn("MONGOID: #{model} has shard config but is emdedded")
|
|
127
127
|
next
|
|
128
128
|
end
|
|
129
129
|
|
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
|
|
@@ -34,15 +34,15 @@ module Mongoid
|
|
|
34
34
|
document.errors.add(
|
|
35
35
|
attribute,
|
|
36
36
|
:blank_in_locale,
|
|
37
|
-
|
|
37
|
+
options.merge(location: _locale)
|
|
38
38
|
) if not_present?(_value)
|
|
39
39
|
end
|
|
40
40
|
elsif document.relations.has_key?(attribute.to_s)
|
|
41
41
|
if relation_or_fk_missing?(document, attribute, value)
|
|
42
|
-
document.errors.add(attribute, :blank,
|
|
42
|
+
document.errors.add(attribute, :blank, options)
|
|
43
43
|
end
|
|
44
44
|
else
|
|
45
|
-
document.errors.add(attribute, :blank,
|
|
45
|
+
document.errors.add(attribute, :blank, options) if not_present?(value)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -68,7 +68,7 @@ module Mongoid
|
|
|
68
68
|
# @since 2.4.10
|
|
69
69
|
def add_error(document, attribute, value)
|
|
70
70
|
document.errors.add(
|
|
71
|
-
attribute, :taken,
|
|
71
|
+
attribute, :taken, options.except(:case_sensitive, :scope).merge(value: value)
|
|
72
72
|
)
|
|
73
73
|
end
|
|
74
74
|
|
data/lib/mongoid/version.rb
CHANGED
data/lib/mongoid.rb
CHANGED
|
@@ -57,7 +57,7 @@ development:
|
|
|
57
57
|
# connect: :direct
|
|
58
58
|
|
|
59
59
|
# Changes the default time in seconds the server monitors refresh their status
|
|
60
|
-
# via
|
|
60
|
+
# via ismaster commands. (default: 10)
|
|
61
61
|
# heartbeat_frequency: 10
|
|
62
62
|
|
|
63
63
|
# The time in seconds for selecting servers for a near read preference. (default: 0.015)
|
|
@@ -297,9 +297,6 @@ describe 'Mongoid application tests' do
|
|
|
297
297
|
end
|
|
298
298
|
|
|
299
299
|
def remove_bundler_req
|
|
300
|
-
return unless File.file?('Gemfile.lock')
|
|
301
|
-
# TODO: Remove this method completely when we get rid of .lock files in
|
|
302
|
-
# mongoid-demo apps.
|
|
303
300
|
lock_lines = IO.readlines('Gemfile.lock')
|
|
304
301
|
# Get rid of the bundled with line so that whatever bundler is installed
|
|
305
302
|
# on the system is usable with the application.
|
|
@@ -21,4 +21,48 @@ describe 'embeds_many associations' do
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
context 'clearing association when parent is not saved' do
|
|
26
|
+
let!(:parent) { Canvas.create!(shapes: [Shape.new]) }
|
|
27
|
+
|
|
28
|
+
let(:unsaved_parent) { Canvas.new(id: parent.id, shapes: [Shape.new]) }
|
|
29
|
+
|
|
30
|
+
context "using #clear" do
|
|
31
|
+
it 'deletes the target from the database' do
|
|
32
|
+
unsaved_parent.shapes.clear
|
|
33
|
+
|
|
34
|
+
unsaved_parent.shapes.should be_empty
|
|
35
|
+
|
|
36
|
+
unsaved_parent.new_record?.should be true
|
|
37
|
+
parent.reload
|
|
38
|
+
parent.shapes.should be_empty
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
shared_examples 'does not delete the target from the database' do
|
|
43
|
+
it 'does not delete the target from the database' do
|
|
44
|
+
unsaved_parent.shapes.should be_empty
|
|
45
|
+
|
|
46
|
+
unsaved_parent.new_record?.should be true
|
|
47
|
+
parent.reload
|
|
48
|
+
parent.shapes.length.should == 1
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "using #delete_all" do
|
|
53
|
+
before do
|
|
54
|
+
unsaved_parent.shapes.delete_all
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
include_examples 'does not delete the target from the database'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "using #destroy_all" do
|
|
61
|
+
before do
|
|
62
|
+
unsaved_parent.shapes.destroy_all
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
include_examples 'does not delete the target from the database'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
24
68
|
end
|
|
@@ -67,6 +67,54 @@ describe 'has_one associations' do
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
context 'when calling methods on target' do
|
|
71
|
+
let(:parent) do
|
|
72
|
+
HomCollege.create!.tap do |college|
|
|
73
|
+
HomAccreditation.create!(college: college)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
shared_examples 'delegates to the field' do |reloaded: false|
|
|
78
|
+
context 'non-conflicting field name' do
|
|
79
|
+
it 'delegates to the field' do
|
|
80
|
+
parent.accreditation.price.should == 42
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'using send' do
|
|
84
|
+
it 'delegates to the field' do
|
|
85
|
+
parent.accreditation.send(:price).should == 42
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context 'field name that conflicts with Kernel' do
|
|
91
|
+
it 'delegates to the field' do
|
|
92
|
+
parent.accreditation.format.should == 'fmt'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'using send' do
|
|
96
|
+
it 'delegates to the field' do
|
|
97
|
+
if reloaded
|
|
98
|
+
pending 'MONGOID-4018'
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
parent.accreditation.send(:format).should == 'fmt'
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
include_examples 'delegates to the field'
|
|
108
|
+
|
|
109
|
+
context 'after reloading parent' do
|
|
110
|
+
before do
|
|
111
|
+
parent.reload
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
include_examples 'delegates to the field', reloaded: true
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
70
118
|
context 'when child does not have parent association' do
|
|
71
119
|
context 'Child.new' do
|
|
72
120
|
it 'creates a child instance' do
|
|
@@ -12,7 +12,7 @@ describe 'Queries on Date fields' do
|
|
|
12
12
|
|
|
13
13
|
shared_examples 'converts to beginning of day in UTC' do
|
|
14
14
|
it 'converts to beginning of day in UTC' do
|
|
15
|
-
selector['founded'].should == arg.
|
|
15
|
+
selector['founded'].should == Time.utc(arg.year, arg.month, arg.day)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -20,6 +20,15 @@ describe Mongoid::Document do
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
context 'when id is unaliased' do
|
|
24
|
+
it 'persists separate id and _id values' do
|
|
25
|
+
shirt = Shirt.create!(id: 'hello', _id: 'foo')
|
|
26
|
+
shirt = Shirt.find(shirt._id)
|
|
27
|
+
shirt.id.should == 'hello'
|
|
28
|
+
shirt._id.should == 'foo'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
23
32
|
describe '#reload' do
|
|
24
33
|
context 'when changing shard key value' do
|
|
25
34
|
require_topology :sharded
|