mongoid 7.3.2 → 7.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/config/locales/en.yml +13 -0
- data/lib/mongoid/association/embedded/batchable.rb +20 -1
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +3 -7
- data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
- data/lib/mongoid/association/relatable.rb +2 -0
- data/lib/mongoid/atomic/paths/embedded/many.rb +19 -0
- data/lib/mongoid/atomic.rb +26 -2
- data/lib/mongoid/config/environment.rb +9 -1
- data/lib/mongoid/contextual/atomic.rb +7 -2
- data/lib/mongoid/contextual/none.rb +3 -0
- data/lib/mongoid/criteria/queryable/selectable.rb +2 -2
- data/lib/mongoid/criteria/queryable/storable.rb +5 -5
- data/lib/mongoid/document.rb +3 -2
- data/lib/mongoid/errors/empty_config_file.rb +26 -0
- data/lib/mongoid/errors/invalid_config_file.rb +26 -0
- data/lib/mongoid/errors.rb +2 -0
- data/lib/mongoid/persistable/upsertable.rb +1 -1
- data/lib/mongoid/persistence_context.rb +3 -1
- data/lib/mongoid/query_cache.rb +11 -1
- data/lib/mongoid/tasks/database.rb +1 -1
- data/lib/mongoid/touchable.rb +10 -0
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +7 -2
- data/spec/integration/associations/embeds_many_spec.rb +139 -0
- data/spec/integration/contextual/empty_spec.rb +142 -0
- data/spec/integration/stringified_symbol_field_spec.rb +2 -2
- data/spec/lite_spec_helper.rb +8 -1
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +21 -0
- data/spec/mongoid/association/embedded/embeds_many_models.rb +137 -0
- data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +20 -0
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +8 -0
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +244 -92
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +30 -14
- data/spec/mongoid/association/referenced/has_many_models.rb +17 -0
- data/spec/mongoid/clients/factory_spec.rb +9 -3
- data/spec/mongoid/clients/options_spec.rb +11 -5
- data/spec/mongoid/config/environment_spec.rb +86 -8
- data/spec/mongoid/config_spec.rb +89 -16
- data/spec/mongoid/contextual/atomic_spec.rb +64 -25
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -1
- data/spec/mongoid/copyable_spec.rb +1 -1
- data/spec/mongoid/criteria_spec.rb +32 -0
- data/spec/mongoid/document_spec.rb +21 -1
- data/spec/mongoid/errors/invalid_config_file_spec.rb +32 -0
- data/spec/mongoid/persistable/updatable_spec.rb +2 -0
- data/spec/mongoid/query_cache_spec.rb +26 -2
- data/spec/mongoid/scopable_spec.rb +11 -0
- data/spec/mongoid/touchable_spec.rb +18 -0
- data/spec/mongoid/touchable_spec_models.rb +2 -0
- data/spec/shared/lib/mrss/cluster_config.rb +6 -1
- data/spec/shared/lib/mrss/constraints.rb +21 -4
- data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +17 -12
- data/spec/shared/lib/mrss/session_registry.rb +69 -0
- data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
- data/spec/shared/share/Dockerfile.erb +8 -7
- data/spec/shared/shlib/server.sh +72 -22
- data/spec/support/models/audible_sound.rb +3 -0
- data.tar.gz.sig +0 -0
- metadata +627 -608
- metadata.gz.sig +0 -0
- data/spec/support/session_registry.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efce0ba93d948e87b85aa1a6e1a0768ecb2bd17a052d5e34afb426c357391492
|
4
|
+
data.tar.gz: 39784e3b229e457971b79962c26e22f3f1e721c68d72268bdafafa821c245c80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f690e5ca59dfdf1e658ac922c5e8c0e0de1bef099f005205cab26b4e27922ce82b64dae38e803673b32e73f9327746562548c3f9667a4d3fd275483729e6ff3d
|
7
|
+
data.tar.gz: b87aef76b5145507b5e48f8516f4b27b99f401d7afb2fa56441d1d47540eac6f3f7bf198fadfd995e9fc08b0563727b6a5c4f7ce5014456e0dd4a6d345cdf3bb
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/config/locales/en.yml
CHANGED
@@ -80,6 +80,12 @@ en:
|
|
80
80
|
different collections so a simple id lookup is not sufficient enough."
|
81
81
|
resolution: "Don't attempt to perform this action and have patience,
|
82
82
|
maybe this will be supported in the future."
|
83
|
+
empty_config_file:
|
84
|
+
message: "Empty configuration file: %{path}."
|
85
|
+
summary: "Your mongoid.yml configuration file appears to be empty."
|
86
|
+
resolution: "Ensure your configuration file contains the correct contents.
|
87
|
+
Please consult the following page with respect to Mongoid's configuration:
|
88
|
+
https://docs.mongodb.com/mongoid/current/reference/configuration/"
|
83
89
|
invalid_collection:
|
84
90
|
message: "Access to the collection for %{klass} is not allowed."
|
85
91
|
summary: "%{klass}.collection was called, and %{klass} is an embedded
|
@@ -94,6 +100,13 @@ en:
|
|
94
100
|
A collation option is only supported if the query is executed on a MongoDB server
|
95
101
|
with version >= 3.4."
|
96
102
|
resolution: "Remove the collation option from the query."
|
103
|
+
invalid_config_file:
|
104
|
+
message: "Invalid configuration file: %{path}."
|
105
|
+
summary: "Your mongoid.yml configuration file does not contain the
|
106
|
+
correct file structure."
|
107
|
+
resolution: "Ensure your configuration file contains the correct contents.
|
108
|
+
Please consult the following page with respect to Mongoid's configuration:
|
109
|
+
https://docs.mongodb.com/mongoid/current/reference/configuration/"
|
97
110
|
invalid_config_option:
|
98
111
|
message: "Invalid configuration option: %{name}."
|
99
112
|
summary: "A invalid configuration option was provided in your
|
@@ -82,6 +82,8 @@ module Mongoid
|
|
82
82
|
def batch_replace(docs)
|
83
83
|
if docs.blank?
|
84
84
|
if _assigning? && !empty?
|
85
|
+
_base.delayed_atomic_sets.delete(path)
|
86
|
+
clear_atomic_path_cache
|
85
87
|
_base.add_atomic_unset(first)
|
86
88
|
target_duplicate = _target.dup
|
87
89
|
pre_process_batch_remove(target_duplicate, :delete)
|
@@ -93,6 +95,8 @@ module Mongoid
|
|
93
95
|
_base.delayed_atomic_sets.clear unless _assigning?
|
94
96
|
docs = normalize_docs(docs).compact
|
95
97
|
_target.clear and _unscoped.clear
|
98
|
+
_base.delayed_atomic_unsets.delete(path)
|
99
|
+
clear_atomic_path_cache
|
96
100
|
inserts = execute_batch_set(docs)
|
97
101
|
add_atomic_sets(inserts)
|
98
102
|
end
|
@@ -250,7 +254,22 @@ module Mongoid
|
|
250
254
|
#
|
251
255
|
# @since 3.0.0
|
252
256
|
def path
|
253
|
-
@path ||= _unscoped.
|
257
|
+
@path ||= if _unscoped.empty?
|
258
|
+
Mongoid::Atomic::Paths::Embedded::Many.position_without_document(_base, _association)
|
259
|
+
else
|
260
|
+
_unscoped.first.atomic_path
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Clear the cache for path and atomic_paths. This method is used when
|
265
|
+
# the path method is used, and the association has not been set on the
|
266
|
+
# document yet, which can cause path and atomic_paths to be calculated
|
267
|
+
# incorrectly later.
|
268
|
+
#
|
269
|
+
# @api private
|
270
|
+
def clear_atomic_path_cache
|
271
|
+
self.path = nil
|
272
|
+
_base.instance_variable_set("@atomic_paths", nil)
|
254
273
|
end
|
255
274
|
|
256
275
|
# Set the atomic path.
|
@@ -209,9 +209,9 @@ module Mongoid
|
|
209
209
|
# @since 2.1.0
|
210
210
|
def empty?
|
211
211
|
if _loaded?
|
212
|
-
in_memory.
|
212
|
+
in_memory.empty?
|
213
213
|
else
|
214
|
-
|
214
|
+
_added.empty? && !_unloaded.exists?
|
215
215
|
end
|
216
216
|
end
|
217
217
|
|
@@ -242,11 +242,7 @@ module Mongoid
|
|
242
242
|
def any?(*args)
|
243
243
|
return super if args.any? || block_given?
|
244
244
|
|
245
|
-
|
246
|
-
in_memory.length > 0
|
247
|
-
else
|
248
|
-
_unloaded.exists? || _added.length > 0
|
249
|
-
end
|
245
|
+
!empty?
|
250
246
|
end
|
251
247
|
|
252
248
|
# Get the first document in the enumerable. Will check the persisted
|
@@ -506,8 +506,8 @@ module Mongoid
|
|
506
506
|
selector = conditions || {}
|
507
507
|
removed = klass.send(method, selector.merge!(criteria.selector))
|
508
508
|
_target.delete_if do |doc|
|
509
|
-
|
510
|
-
unbind_one(doc)
|
509
|
+
doc._matches?(selector).tap do |b|
|
510
|
+
unbind_one(doc) if b
|
511
511
|
end
|
512
512
|
end
|
513
513
|
removed
|
@@ -39,6 +39,25 @@ module Mongoid
|
|
39
39
|
locator = document.new_record? ? "" : ".#{document._index}"
|
40
40
|
"#{pos}#{"." unless pos.blank?}#{document._association.store_as}#{locator}"
|
41
41
|
end
|
42
|
+
|
43
|
+
class << self
|
44
|
+
|
45
|
+
# Get the position of where the document would go for the given
|
46
|
+
# association. The use case for this function is when trying to
|
47
|
+
# persist an empty list for an embedded association. All of the
|
48
|
+
# existing functions for getting the position to store a document
|
49
|
+
# require passing in a document to store, which we don't have when
|
50
|
+
# trying to store the empty list.
|
51
|
+
#
|
52
|
+
# @param [ Document ] parent The parent document to store in.
|
53
|
+
# @param [ Association ] association The association.
|
54
|
+
#
|
55
|
+
# @return [ String ] The position string.
|
56
|
+
def position_without_document(parent, association)
|
57
|
+
pos = parent.atomic_position
|
58
|
+
"#{pos}#{"." unless pos.blank?}#{association.store_as}"
|
59
|
+
end
|
60
|
+
end
|
42
61
|
end
|
43
62
|
end
|
44
63
|
end
|
data/lib/mongoid/atomic.rb
CHANGED
@@ -385,11 +385,35 @@ module Mongoid
|
|
385
385
|
updates = atomic_updates
|
386
386
|
return {} unless atomic_updates.key?("$set")
|
387
387
|
touches = {}
|
388
|
+
wanted_keys = %w(updated_at u_at)
|
389
|
+
# TODO this permits field to be passed as an empty string in which case
|
390
|
+
# it is ignored, get rid of this behavior.
|
391
|
+
if field.present?
|
392
|
+
wanted_keys << field.to_s
|
393
|
+
end
|
388
394
|
updates["$set"].each_pair do |key, value|
|
389
|
-
|
390
|
-
|
395
|
+
if wanted_keys.include?(key.split('.').last)
|
396
|
+
touches.update(key => value)
|
397
|
+
end
|
391
398
|
end
|
392
399
|
{ "$set" => touches }
|
393
400
|
end
|
401
|
+
|
402
|
+
# Returns the $set atomic updates affecting the specified field.
|
403
|
+
#
|
404
|
+
# @param [ String ] field The field name.
|
405
|
+
#
|
406
|
+
# @api private
|
407
|
+
def set_field_atomic_updates(field)
|
408
|
+
updates = atomic_updates
|
409
|
+
return {} unless atomic_updates.key?("$set")
|
410
|
+
sets = {}
|
411
|
+
updates["$set"].each_pair do |key, value|
|
412
|
+
if key.split('.').last == field
|
413
|
+
sets.update(key => value)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
{ "$set" => sets }
|
417
|
+
end
|
394
418
|
end
|
395
419
|
end
|
@@ -52,7 +52,15 @@ module Mongoid
|
|
52
52
|
# @api private
|
53
53
|
def load_yaml(path, environment = nil)
|
54
54
|
env = environment ? environment.to_s : env_name
|
55
|
-
|
55
|
+
contents = File.new(path).read
|
56
|
+
if contents.empty?
|
57
|
+
raise Mongoid::Errors::EmptyConfigFile.new(path)
|
58
|
+
end
|
59
|
+
data = YAML.load(ERB.new(contents).result)
|
60
|
+
unless data.is_a?(Hash)
|
61
|
+
raise Mongoid::Errors::InvalidConfigFile.new(path)
|
62
|
+
end
|
63
|
+
data[env]
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -173,13 +173,18 @@ module Mongoid
|
|
173
173
|
# @example Unset the field on the matches.
|
174
174
|
# context.unset(:name)
|
175
175
|
#
|
176
|
-
# @param [ String
|
176
|
+
# @param [ String | Symbol | Array<String|Symbol> | Hash ] args
|
177
|
+
# The name(s) of the field(s) to unset.
|
178
|
+
# If a Hash is specified, its keys will be used irrespective of what
|
179
|
+
# each key's value is, even if the value is nil or false.
|
177
180
|
#
|
178
181
|
# @return [ nil ] Nil.
|
179
182
|
#
|
180
183
|
# @since 3.0.0
|
181
184
|
def unset(*args)
|
182
|
-
fields = args.
|
185
|
+
fields = args.map { |a| a.is_a?(Hash) ? a.keys : a }
|
186
|
+
.__find_args__
|
187
|
+
.map { |f| [database_field_name(f), true] }
|
183
188
|
view.update_many("$unset" => Hash[fields])
|
184
189
|
end
|
185
190
|
|
@@ -597,7 +597,7 @@ module Mongoid
|
|
597
597
|
end
|
598
598
|
_mongoid_expand_keys(new_s).each do |k, v|
|
599
599
|
k = k.to_s
|
600
|
-
if c.selector[k] || k
|
600
|
+
if c.selector[k] || k.start_with?('$')
|
601
601
|
c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
|
602
602
|
else
|
603
603
|
if v.is_a?(Hash)
|
@@ -890,7 +890,7 @@ module Mongoid
|
|
890
890
|
clone.tap do |query|
|
891
891
|
normalized.each do |field, value|
|
892
892
|
field_s = field.to_s
|
893
|
-
if field_s
|
893
|
+
if field_s.start_with?('$')
|
894
894
|
# Query expression-level operator, like $and or $where
|
895
895
|
query.add_operator_expression(field_s, value)
|
896
896
|
else
|
@@ -38,7 +38,7 @@ module Mongoid
|
|
38
38
|
raise ArgumentError, "Field must be a string: #{field}"
|
39
39
|
end
|
40
40
|
|
41
|
-
if field
|
41
|
+
if field.start_with?('$')
|
42
42
|
raise ArgumentError, "Field cannot be an operator (i.e. begin with $): #{field}"
|
43
43
|
end
|
44
44
|
|
@@ -48,14 +48,14 @@ module Mongoid
|
|
48
48
|
if value.is_a?(Hash) && selector[field].is_a?(Hash) &&
|
49
49
|
value.keys.all? { |key|
|
50
50
|
key_s = key.to_s
|
51
|
-
key_s
|
51
|
+
key_s.start_with?('$') && !selector[field].key?(key_s)
|
52
52
|
}
|
53
53
|
then
|
54
54
|
# Multiple operators can be combined on the same field by
|
55
55
|
# adding them to the existing hash.
|
56
56
|
new_value = selector[field].merge(value)
|
57
57
|
selector.store(field, new_value)
|
58
|
-
|
58
|
+
elsif selector[field] != value
|
59
59
|
add_operator_expression('$and', [{field => value}])
|
60
60
|
end
|
61
61
|
else
|
@@ -185,7 +185,7 @@ module Mongoid
|
|
185
185
|
raise ArgumentError, "Operator must be a string: #{operator}"
|
186
186
|
end
|
187
187
|
|
188
|
-
unless operator
|
188
|
+
unless operator.start_with?('$')
|
189
189
|
raise ArgumentError, "Operator must begin with $: #{operator}"
|
190
190
|
end
|
191
191
|
|
@@ -220,7 +220,7 @@ module Mongoid
|
|
220
220
|
raise ArgumentError, "Field must be a string: #{field}"
|
221
221
|
end
|
222
222
|
|
223
|
-
if field
|
223
|
+
if field.start_with?('$')
|
224
224
|
add_operator_expression(field, value)
|
225
225
|
else
|
226
226
|
add_field_expression(field, value)
|
data/lib/mongoid/document.rb
CHANGED
@@ -194,8 +194,8 @@ module Mongoid
|
|
194
194
|
#
|
195
195
|
# @param [ Hash ] options The options.
|
196
196
|
#
|
197
|
-
# @option options [ true, false ] :compact Whether to include fields
|
198
|
-
# nil values in the json document.
|
197
|
+
# @option options [ true, false ] :compact (Deprecated) Whether to include fields
|
198
|
+
# with nil values in the json document.
|
199
199
|
#
|
200
200
|
# @return [ Hash ] The document as json.
|
201
201
|
#
|
@@ -203,6 +203,7 @@ module Mongoid
|
|
203
203
|
def as_json(options = nil)
|
204
204
|
rv = super
|
205
205
|
if options && options[:compact]
|
206
|
+
Mongoid.logger.warn('#as_json :compact option is deprecated. Please call #compact on the returned Hash object instead.')
|
206
207
|
rv = rv.compact
|
207
208
|
end
|
208
209
|
rv
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module Mongoid
|
5
|
+
module Errors
|
6
|
+
|
7
|
+
# This error is raised when an empty configuration file is attempted to be
|
8
|
+
# loaded.
|
9
|
+
class EmptyConfigFile < MongoidError
|
10
|
+
|
11
|
+
# Create the new error.
|
12
|
+
#
|
13
|
+
# @param [ String ] path The path of the config file used.
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
def initialize(path)
|
17
|
+
super(
|
18
|
+
compose_message(
|
19
|
+
"empty_config_file",
|
20
|
+
{ path: path }
|
21
|
+
)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module Mongoid
|
5
|
+
module Errors
|
6
|
+
|
7
|
+
# This error is raised when a bad configuration file is attempted to be
|
8
|
+
# loaded.
|
9
|
+
class InvalidConfigFile < MongoidError
|
10
|
+
|
11
|
+
# Create the new error.
|
12
|
+
#
|
13
|
+
# @param [ String ] path The path of the config file used.
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
def initialize(path)
|
17
|
+
super(
|
18
|
+
compose_message(
|
19
|
+
"invalid_config_file",
|
20
|
+
{ path: path }
|
21
|
+
)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/mongoid/errors.rb
CHANGED
@@ -8,8 +8,10 @@ require "mongoid/errors/criteria_argument_required"
|
|
8
8
|
require "mongoid/errors/document_not_destroyed"
|
9
9
|
require "mongoid/errors/document_not_found"
|
10
10
|
require "mongoid/errors/eager_load"
|
11
|
+
require "mongoid/errors/empty_config_file"
|
11
12
|
require "mongoid/errors/in_memory_collation_not_supported"
|
12
13
|
require "mongoid/errors/invalid_collection"
|
14
|
+
require "mongoid/errors/invalid_config_file"
|
13
15
|
require "mongoid/errors/invalid_config_option"
|
14
16
|
require "mongoid/errors/invalid_dependent_strategy"
|
15
17
|
require "mongoid/errors/invalid_field"
|
@@ -237,7 +237,9 @@ 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
|
-
|
240
|
+
unless cluster.nil? || context.cluster.equal?(cluster)
|
241
|
+
context.client.close
|
242
|
+
end
|
241
243
|
end
|
242
244
|
ensure
|
243
245
|
Thread.current["[mongoid][#{object.object_id}]:context"] = original_context
|
data/lib/mongoid/query_cache.rb
CHANGED
@@ -7,8 +7,14 @@ module Mongoid
|
|
7
7
|
#
|
8
8
|
# @since 4.0.0
|
9
9
|
module QueryCache
|
10
|
-
|
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
|
11
16
|
|
17
|
+
class << self
|
12
18
|
# Get the cached queries.
|
13
19
|
#
|
14
20
|
# @example Get the cached queries from the current thread.
|
@@ -86,6 +92,10 @@ module Mongoid
|
|
86
92
|
if defined?(Mongo::QueryCache)
|
87
93
|
Mongo::QueryCache.cache(&block)
|
88
94
|
else
|
95
|
+
@legacy_query_cache_warned ||= begin
|
96
|
+
Mongoid.logger.warn(LEGACY_WARNING)
|
97
|
+
true
|
98
|
+
end
|
89
99
|
enabled = QueryCache.enabled?
|
90
100
|
QueryCache.enabled = true
|
91
101
|
begin
|
@@ -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 embedded")
|
127
127
|
next
|
128
128
|
end
|
129
129
|
|
data/lib/mongoid/touchable.rb
CHANGED
@@ -41,6 +41,16 @@ module Mongoid
|
|
41
41
|
# _association.inverse_association.options but inverse_association
|
42
42
|
# seems to not always/ever be set here. See MONGOID-5014.
|
43
43
|
_parent.touch
|
44
|
+
|
45
|
+
if field
|
46
|
+
# If we are told to also touch a field, perform a separate write
|
47
|
+
# for that field. See MONGOID-5136.
|
48
|
+
# In theory we should combine the writes, which would require
|
49
|
+
# passing the fields to be updated to the parents - MONGOID-5142.
|
50
|
+
sets = set_field_atomic_updates(field)
|
51
|
+
selector = atomic_selector
|
52
|
+
_root.collection.find(selector).update_one(positionally(selector, sets), session: _session)
|
53
|
+
end
|
44
54
|
else
|
45
55
|
# If the current document is not embedded, it is composition root
|
46
56
|
# and we need to persist the write here.
|
data/lib/mongoid/version.rb
CHANGED
@@ -80,8 +80,13 @@ development:
|
|
80
80
|
# (default: 10)
|
81
81
|
# connect_timeout: 10
|
82
82
|
|
83
|
-
#
|
84
|
-
#
|
83
|
+
# How long to wait for a response for each operation sent to the
|
84
|
+
# server. This timeout should be set to a value larger than the
|
85
|
+
# processing time for the longest operation that will be executed
|
86
|
+
# by the application. Note that this is a client-side timeout;
|
87
|
+
# the server may continue executing an operation after the client
|
88
|
+
# aborts it with the SocketTimeout exception.
|
89
|
+
# (default: nil, meaning no timeout)
|
85
90
|
# socket_timeout: 5
|
86
91
|
|
87
92
|
# The name of the replica set to connect to. Servers provided as seeds that do
|
@@ -65,4 +65,143 @@ describe 'embeds_many associations' do
|
|
65
65
|
include_examples 'does not delete the target from the database'
|
66
66
|
end
|
67
67
|
end
|
68
|
+
|
69
|
+
context 'assigning attributes to the same association' do
|
70
|
+
context 'setting then clearing' do
|
71
|
+
let(:canvas) do
|
72
|
+
Canvas.create!(shapes: [Shape.new])
|
73
|
+
end
|
74
|
+
|
75
|
+
shared_examples 'persists correctly' do
|
76
|
+
it 'persists correctly' do
|
77
|
+
canvas.shapes.should be_empty
|
78
|
+
_canvas = Canvas.find(canvas.id)
|
79
|
+
_canvas.shapes.should be_empty
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'via assignment operator' do
|
84
|
+
before do
|
85
|
+
canvas.shapes = [Shape.new, Shape.new]
|
86
|
+
canvas.shapes = []
|
87
|
+
canvas.save!
|
88
|
+
end
|
89
|
+
|
90
|
+
include_examples 'persists correctly'
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'via attributes=' do
|
94
|
+
before do
|
95
|
+
canvas.attributes = {shapes: [Shape.new, Shape.new]}
|
96
|
+
canvas.attributes = {shapes: []}
|
97
|
+
canvas.save!
|
98
|
+
end
|
99
|
+
|
100
|
+
include_examples 'persists correctly'
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'via assign_attributes' do
|
104
|
+
before do
|
105
|
+
canvas.assign_attributes(shapes: [Shape.new, Shape.new])
|
106
|
+
canvas.assign_attributes(shapes: [])
|
107
|
+
canvas.save!
|
108
|
+
end
|
109
|
+
|
110
|
+
include_examples 'persists correctly'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'clearing then setting' do
|
115
|
+
let(:canvas) do
|
116
|
+
Canvas.create!(shapes: [Shape.new])
|
117
|
+
end
|
118
|
+
|
119
|
+
shared_examples 'persists correctly' do
|
120
|
+
it 'persists correctly' do
|
121
|
+
canvas.shapes.length.should eq 2
|
122
|
+
_canvas = Canvas.find(canvas.id)
|
123
|
+
_canvas.shapes.length.should eq 2
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'via assignment operator' do
|
128
|
+
before do
|
129
|
+
canvas.shapes = []
|
130
|
+
canvas.shapes = [Shape.new, Shape.new]
|
131
|
+
canvas.save!
|
132
|
+
end
|
133
|
+
|
134
|
+
include_examples 'persists correctly'
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'via attributes=' do
|
138
|
+
before do
|
139
|
+
canvas.attributes = {shapes: []}
|
140
|
+
canvas.attributes = {shapes: [Shape.new, Shape.new]}
|
141
|
+
canvas.save!
|
142
|
+
end
|
143
|
+
|
144
|
+
include_examples 'persists correctly'
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'via assign_attributes' do
|
148
|
+
before do
|
149
|
+
canvas.assign_attributes(shapes: [])
|
150
|
+
canvas.assign_attributes(shapes: [Shape.new, Shape.new])
|
151
|
+
canvas.save!
|
152
|
+
end
|
153
|
+
|
154
|
+
include_examples 'persists correctly'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'updating a child then clearing' do
|
159
|
+
let(:canvas) do
|
160
|
+
Canvas.create!(shapes: [Shape.new])
|
161
|
+
end
|
162
|
+
|
163
|
+
shared_examples 'persists correctly' do
|
164
|
+
it 'persists correctly' do
|
165
|
+
canvas.shapes.should be_empty
|
166
|
+
_canvas = Canvas.find(canvas.id)
|
167
|
+
_canvas.shapes.should be_empty
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'via assignment operator' do
|
172
|
+
before do
|
173
|
+
# Mongoid uses the new value of `x` in the $pullAll query,
|
174
|
+
# which doesn't match the document that is in the database,
|
175
|
+
# resulting in the empty array assignment not taking effect.
|
176
|
+
pending 'MONGOID-5037'
|
177
|
+
|
178
|
+
canvas.shapes.first.x = 1
|
179
|
+
canvas.shapes = []
|
180
|
+
canvas.save!
|
181
|
+
end
|
182
|
+
|
183
|
+
include_examples 'persists correctly'
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'via attributes=' do
|
187
|
+
before do
|
188
|
+
canvas.shapes.first.x = 1
|
189
|
+
canvas.attributes = {shapes: []}
|
190
|
+
canvas.save!
|
191
|
+
end
|
192
|
+
|
193
|
+
include_examples 'persists correctly'
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'via assign_attributes' do
|
197
|
+
before do
|
198
|
+
canvas.shapes.first.x = 1
|
199
|
+
canvas.assign_attributes(shapes: [])
|
200
|
+
canvas.save!
|
201
|
+
end
|
202
|
+
|
203
|
+
include_examples 'persists correctly'
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
68
207
|
end
|