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
|
@@ -220,7 +220,7 @@ module Mongoid
|
|
|
220
220
|
#
|
|
221
221
|
# @since 2.0.0.beta.1
|
|
222
222
|
def initialize(base, target, association)
|
|
223
|
-
enum = HasMany::
|
|
223
|
+
enum = HasMany::Enumerable.new(target, base, association)
|
|
224
224
|
init(base, enum, association) do
|
|
225
225
|
raise_mixed if klass.embedded? && !klass.cyclic?
|
|
226
226
|
end
|
|
@@ -367,7 +367,7 @@ module Mongoid
|
|
|
367
367
|
document.persisted? &&
|
|
368
368
|
document._association &&
|
|
369
369
|
document.respond_to?(document._association.foreign_key) &&
|
|
370
|
-
document.__send__(document._association.foreign_key) == _base.
|
|
370
|
+
document.__send__(document._association.foreign_key) == _base._id
|
|
371
371
|
end
|
|
372
372
|
|
|
373
373
|
# Instantiate the binding associated with this association.
|
|
@@ -443,7 +443,7 @@ module Mongoid
|
|
|
443
443
|
# @return [ Criteria, Object ] A Criteria or return value from the target.
|
|
444
444
|
#
|
|
445
445
|
# @since 2.0.0.beta.1
|
|
446
|
-
|
|
446
|
+
def method_missing(name, *args, &block)
|
|
447
447
|
if _target.respond_to?(name)
|
|
448
448
|
_target.send(name, *args, &block)
|
|
449
449
|
else
|
|
@@ -69,7 +69,7 @@ module Mongoid
|
|
|
69
69
|
#
|
|
70
70
|
# @since 2.0.0
|
|
71
71
|
def acceptable_id?
|
|
72
|
-
id = convert_id(existing.class, attributes[:
|
|
72
|
+
id = convert_id(existing.class, attributes[:_id])
|
|
73
73
|
existing._id == id || id.nil? || (existing._id != id && update_only?)
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -82,7 +82,7 @@ module Mongoid
|
|
|
82
82
|
#
|
|
83
83
|
# @since 2.0.0
|
|
84
84
|
def delete?
|
|
85
|
-
destroyable? && !attributes[:
|
|
85
|
+
destroyable? && !attributes[:_id].nil?
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# Can the existing association potentially be destroyed?
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
module Mongoid
|
|
5
|
+
module Attributes
|
|
6
|
+
|
|
7
|
+
# This module defines projection helpers.
|
|
8
|
+
#
|
|
9
|
+
# Projection rules are rather non-trivial. See
|
|
10
|
+
# https://docs.mongodb.com/manual/reference/method/db.collection.find/#find-projection
|
|
11
|
+
# for server documentation.
|
|
12
|
+
# 4.4 server (and presumably all older ones) requires that a projection
|
|
13
|
+
# for content fields is either exclusionary or inclusionary, i.e. one
|
|
14
|
+
# cannot mix exclusions and inclusions in the same query.
|
|
15
|
+
# However, _id can be excluded in a projection that includes content
|
|
16
|
+
# fields.
|
|
17
|
+
# Integer projection values other than 0 and 1 aren't officially
|
|
18
|
+
# documented as of this writing; see DOCSP-15266.
|
|
19
|
+
# 4.4 server also allows nested hash projection specification
|
|
20
|
+
# in addition to dot notation, which I assume Mongoid doesn't handle yet.
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
class Projector
|
|
24
|
+
def initialize(projection)
|
|
25
|
+
if projection
|
|
26
|
+
@content_projection = projection.dup
|
|
27
|
+
@content_projection.delete('_id')
|
|
28
|
+
@id_projection_value = projection['_id']
|
|
29
|
+
else
|
|
30
|
+
@content_projection = nil
|
|
31
|
+
@id_projection_value = nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
attr_reader :id_projection_value
|
|
36
|
+
attr_reader :content_projection
|
|
37
|
+
|
|
38
|
+
# Determine if the specified attribute, or a dot notation path, is allowed
|
|
39
|
+
# by the configured projection, if any.
|
|
40
|
+
#
|
|
41
|
+
# If there is no configured projection, returns true.
|
|
42
|
+
#
|
|
43
|
+
# @param [ String ] name The name of the attribute or a dot notation path.
|
|
44
|
+
#
|
|
45
|
+
# @return [ true, false ] Whether the attribute is allowed by projection.
|
|
46
|
+
#
|
|
47
|
+
# @api private
|
|
48
|
+
def attribute_or_path_allowed?(name)
|
|
49
|
+
# Special handling for _id.
|
|
50
|
+
if name == '_id'
|
|
51
|
+
result = unless id_projection_value.nil?
|
|
52
|
+
value_inclusionary?(id_projection_value)
|
|
53
|
+
else
|
|
54
|
+
true
|
|
55
|
+
end
|
|
56
|
+
return result
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if content_projection.nil?
|
|
60
|
+
# No projection (as opposed to an empty projection).
|
|
61
|
+
# All attributes are allowed.
|
|
62
|
+
return true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Find an item which matches or is a parent of the requested name/path.
|
|
66
|
+
# This handles the case when, for example, the projection was
|
|
67
|
+
# {foo: true} and we want to know if foo.bar is allowed.
|
|
68
|
+
item, value = content_projection.detect do |path, value|
|
|
69
|
+
(name + '.').start_with?(path + '.')
|
|
70
|
+
end
|
|
71
|
+
if item
|
|
72
|
+
return value_inclusionary?(value)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if content_inclusionary?
|
|
76
|
+
# Find an item which would be a strict child of the requested name/path.
|
|
77
|
+
# This handles the case when, for example, the projection was
|
|
78
|
+
# {"foo.bar" => true} and we want to know if foo is allowed.
|
|
79
|
+
# (It is as a container of bars.)
|
|
80
|
+
item, value = content_projection.detect do |path, value|
|
|
81
|
+
(path + '.').start_with?(name + '.')
|
|
82
|
+
end
|
|
83
|
+
if item
|
|
84
|
+
return true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
!content_inclusionary?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
# Determines whether the projection for content fields is inclusionary.
|
|
94
|
+
#
|
|
95
|
+
# An empty projection is inclusionary.
|
|
96
|
+
def content_inclusionary?
|
|
97
|
+
if content_projection.empty?
|
|
98
|
+
return value_inclusionary?(id_projection_value)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
value_inclusionary?(content_projection.values.first)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def value_inclusionary?(value)
|
|
105
|
+
case value
|
|
106
|
+
when Integer
|
|
107
|
+
value >= 1
|
|
108
|
+
when true
|
|
109
|
+
true
|
|
110
|
+
when false
|
|
111
|
+
false
|
|
112
|
+
else
|
|
113
|
+
# The various expressions that are permitted as projection arguments
|
|
114
|
+
# imply an inclusionary projection.
|
|
115
|
+
true
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
data/lib/mongoid/attributes.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "active_model/attribute_methods"
|
|
|
5
5
|
require "mongoid/attributes/dynamic"
|
|
6
6
|
require "mongoid/attributes/nested"
|
|
7
7
|
require "mongoid/attributes/processing"
|
|
8
|
+
require "mongoid/attributes/projector"
|
|
8
9
|
require "mongoid/attributes/readonly"
|
|
9
10
|
|
|
10
11
|
module Mongoid
|
|
@@ -238,11 +239,7 @@ module Mongoid
|
|
|
238
239
|
#
|
|
239
240
|
# @since 4.0.0
|
|
240
241
|
def attribute_missing?(name)
|
|
241
|
-
|
|
242
|
-
return false unless selection
|
|
243
|
-
field = fields[name]
|
|
244
|
-
(selection.values.first == 0 && selection_excluded?(name, selection, field)) ||
|
|
245
|
-
(selection.values.first == 1 && !selection_included?(name, selection, field))
|
|
242
|
+
!Projector.new(__selected_fields).attribute_or_path_allowed?(name)
|
|
246
243
|
end
|
|
247
244
|
|
|
248
245
|
# Return type-casted attributes.
|
|
@@ -259,14 +256,6 @@ module Mongoid
|
|
|
259
256
|
|
|
260
257
|
private
|
|
261
258
|
|
|
262
|
-
def selection_excluded?(name, selection, field)
|
|
263
|
-
selection[name] == 0
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
def selection_included?(name, selection, field)
|
|
267
|
-
selection.key?(name) || selection.keys.collect { |k| k.partition('.').first }.include?(name)
|
|
268
|
-
end
|
|
269
|
-
|
|
270
259
|
# Does the string contain dot syntax for accessing hashes?
|
|
271
260
|
#
|
|
272
261
|
# @api private
|
|
@@ -300,9 +289,11 @@ module Mongoid
|
|
|
300
289
|
|
|
301
290
|
def read_raw_attribute(name)
|
|
302
291
|
normalized = database_field_name(name.to_s)
|
|
292
|
+
|
|
303
293
|
if attribute_missing?(normalized)
|
|
304
294
|
raise ActiveModel::MissingAttributeError, "Missing attribute: '#{name}'"
|
|
305
295
|
end
|
|
296
|
+
|
|
306
297
|
if hash_dot_syntax?(normalized)
|
|
307
298
|
attributes.__nested__(normalized)
|
|
308
299
|
else
|
|
@@ -341,6 +332,26 @@ module Mongoid
|
|
|
341
332
|
alias_method "#{name}_will_change!", "#{original}_will_change!"
|
|
342
333
|
alias_method "#{name}_before_type_cast", "#{original}_before_type_cast"
|
|
343
334
|
end
|
|
335
|
+
|
|
336
|
+
# Removes a field alias.
|
|
337
|
+
#
|
|
338
|
+
# @param [ Symbol ] name The aliased field name to remove.
|
|
339
|
+
def unalias_attribute(name)
|
|
340
|
+
unless aliased_fields.delete(name.to_s)
|
|
341
|
+
raise AttributeError, "Field #{name} is not an aliased field"
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
remove_method name
|
|
345
|
+
remove_method "#{name}="
|
|
346
|
+
remove_method "#{name}?"
|
|
347
|
+
remove_method "#{name}_change"
|
|
348
|
+
remove_method "#{name}_changed?"
|
|
349
|
+
remove_method "reset_#{name}!"
|
|
350
|
+
remove_method "reset_#{name}_to_default!"
|
|
351
|
+
remove_method "#{name}_was"
|
|
352
|
+
remove_method "#{name}_will_change!"
|
|
353
|
+
remove_method "#{name}_before_type_cast"
|
|
354
|
+
end
|
|
344
355
|
end
|
|
345
356
|
|
|
346
357
|
private
|
data/lib/mongoid/cacheable.rb
CHANGED
|
@@ -31,8 +31,8 @@ module Mongoid
|
|
|
31
31
|
# @since 2.4.0
|
|
32
32
|
def cache_key
|
|
33
33
|
return "#{model_key}/new" if new_record?
|
|
34
|
-
return "#{model_key}/#{
|
|
35
|
-
"#{model_key}/#{
|
|
34
|
+
return "#{model_key}/#{_id}-#{updated_at.utc.to_s(cache_timestamp_format)}" if do_or_do_not(:updated_at)
|
|
35
|
+
"#{model_key}/#{_id}"
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -5,6 +5,7 @@ module Mongoid
|
|
|
5
5
|
module Clients
|
|
6
6
|
module Factory
|
|
7
7
|
extend self
|
|
8
|
+
extend Loggable
|
|
8
9
|
|
|
9
10
|
# Create a new client given the named configuration. If no name is
|
|
10
11
|
# provided, return a new client with the default configuration. If a
|
|
@@ -59,12 +60,20 @@ module Mongoid
|
|
|
59
60
|
# @since 3.0.0
|
|
60
61
|
def create_client(configuration)
|
|
61
62
|
raise Errors::NoClientsConfig.new unless configuration
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
config = configuration.dup
|
|
64
|
+
uri = config.delete(:uri)
|
|
65
|
+
database = config.delete(:database)
|
|
66
|
+
hosts = config.delete(:hosts)
|
|
67
|
+
opts = config.delete(:options) || {}
|
|
68
|
+
unless config.empty?
|
|
69
|
+
default_logger.warn("Unknown config options detected: #{config}.")
|
|
70
|
+
end
|
|
71
|
+
if uri
|
|
72
|
+
Mongo::Client.new(uri, options(opts))
|
|
64
73
|
else
|
|
65
74
|
Mongo::Client.new(
|
|
66
|
-
|
|
67
|
-
options(
|
|
75
|
+
hosts,
|
|
76
|
+
options(opts).merge(database: database)
|
|
68
77
|
)
|
|
69
78
|
end
|
|
70
79
|
end
|
|
@@ -78,9 +87,14 @@ module Mongoid
|
|
|
78
87
|
Mongo::VERSION.split('.')[0...2].map(&:to_i)
|
|
79
88
|
end
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
# Prepare options for Mongo::Client based on Mongoid client configuration.
|
|
91
|
+
#
|
|
92
|
+
# @param [ Hash ] opts Parameters from options section of Mongoid client configuration.
|
|
93
|
+
# @return [ Hash ] Options that should be passed to Mongo::Client constructor.
|
|
94
|
+
#
|
|
95
|
+
# @api private
|
|
96
|
+
def options(opts)
|
|
97
|
+
options = opts.dup
|
|
84
98
|
options[:platform] = PLATFORM_DETAILS
|
|
85
99
|
options[:app_name] = Mongoid::Config.app_name if Mongoid::Config.app_name
|
|
86
100
|
if (driver_version <=> [2, 13]) >= 0
|
|
@@ -91,7 +105,7 @@ module Mongoid
|
|
|
91
105
|
end
|
|
92
106
|
options[:wrapping_libraries] = wrap_lib
|
|
93
107
|
end
|
|
94
|
-
options.reject{ |k,
|
|
108
|
+
options.reject{ |k, _v| k == :hosts }.to_hash.symbolize_keys!
|
|
95
109
|
end
|
|
96
110
|
end
|
|
97
111
|
end
|
data/lib/mongoid/clients.rb
CHANGED
|
@@ -59,7 +59,7 @@ module Mongoid
|
|
|
59
59
|
# @example Get a client with the name.
|
|
60
60
|
# Mongoid::Clients.with_name(:replica)
|
|
61
61
|
#
|
|
62
|
-
# @param [ Symbol ] name The name of the client.
|
|
62
|
+
# @param [ String | Symbol ] name The name of the client.
|
|
63
63
|
#
|
|
64
64
|
# @return [ Mongo::Client ] The named client.
|
|
65
65
|
#
|
|
@@ -52,15 +52,7 @@ module Mongoid
|
|
|
52
52
|
# @api private
|
|
53
53
|
def load_yaml(path, environment = nil)
|
|
54
54
|
env = environment ? environment.to_s : env_name
|
|
55
|
-
|
|
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]
|
|
55
|
+
YAML.load(ERB.new(File.new(path).read).result)[env]
|
|
64
56
|
end
|
|
65
57
|
end
|
|
66
58
|
end
|
data/lib/mongoid/config.rb
CHANGED
|
@@ -220,7 +220,7 @@ module Mongoid
|
|
|
220
220
|
#
|
|
221
221
|
# @since 2.0.2
|
|
222
222
|
def purge!
|
|
223
|
-
|
|
223
|
+
global_client.database.collections.each(&:drop) and true
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
# Truncate all data in all collections, but not the indexes.
|
|
@@ -234,7 +234,7 @@ module Mongoid
|
|
|
234
234
|
#
|
|
235
235
|
# @since 2.0.2
|
|
236
236
|
def truncate!
|
|
237
|
-
|
|
237
|
+
global_client.database.collections.each do |collection|
|
|
238
238
|
collection.find.delete_many
|
|
239
239
|
end and true
|
|
240
240
|
end
|
|
@@ -305,5 +305,22 @@ module Mongoid
|
|
|
305
305
|
Validators::Client.validate(c)
|
|
306
306
|
@clients = c
|
|
307
307
|
end
|
|
308
|
+
|
|
309
|
+
# Get database client that respects global overrides
|
|
310
|
+
# Config.override_database and Config.override_client.
|
|
311
|
+
#
|
|
312
|
+
# @return [Mongo::Client] Client according to global overrides.
|
|
313
|
+
def global_client
|
|
314
|
+
client = if Threaded.client_override
|
|
315
|
+
Clients.with_name(Threaded.client_override)
|
|
316
|
+
else
|
|
317
|
+
Clients.default
|
|
318
|
+
end
|
|
319
|
+
if Threaded.database_override
|
|
320
|
+
client.use(Threaded.database_override)
|
|
321
|
+
else
|
|
322
|
+
client
|
|
323
|
+
end
|
|
324
|
+
end
|
|
308
325
|
end
|
|
309
326
|
end
|
|
@@ -11,17 +11,19 @@ module Mongoid
|
|
|
11
11
|
#
|
|
12
12
|
# @example Get all the aggregate values.
|
|
13
13
|
# aggregable.aggregates(:likes)
|
|
14
|
+
# # => {
|
|
15
|
+
# # "count" => 2.0,
|
|
16
|
+
# # "max" => 1000.0,
|
|
17
|
+
# # "min" => 500.0,
|
|
18
|
+
# # "sum" => 1500.0,
|
|
19
|
+
# # "avg" => 750.0
|
|
20
|
+
# # }
|
|
14
21
|
#
|
|
15
22
|
# @param [ String, Symbol ] field The field name.
|
|
16
23
|
#
|
|
17
|
-
# @return [ Hash ] count is a number of documents with the provided
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# "max" => 1000.0,
|
|
21
|
-
# "min" => 500.0,
|
|
22
|
-
# "sum" => 1500.0,
|
|
23
|
-
# "avg" => 750.0
|
|
24
|
-
# }
|
|
24
|
+
# @return [ Hash ] count is a number of documents with the provided
|
|
25
|
+
# field. If there're none, then count is 0 and max, min, sum, avg
|
|
26
|
+
# are nil.
|
|
25
27
|
#
|
|
26
28
|
# @since 3.0.0
|
|
27
29
|
def aggregates(field)
|
|
@@ -173,18 +173,13 @@ module Mongoid
|
|
|
173
173
|
# @example Unset the field on the matches.
|
|
174
174
|
# context.unset(:name)
|
|
175
175
|
#
|
|
176
|
-
# @param [ String
|
|
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.
|
|
176
|
+
# @param [ String, Symbol, Array ] args The name of the fields.
|
|
180
177
|
#
|
|
181
178
|
# @return [ nil ] Nil.
|
|
182
179
|
#
|
|
183
180
|
# @since 3.0.0
|
|
184
181
|
def unset(*args)
|
|
185
|
-
fields = args.
|
|
186
|
-
.__find_args__
|
|
187
|
-
.map { |f| [database_field_name(f), true] }
|
|
182
|
+
fields = args.__find_args__.collect { |f| [database_field_name(f), true] }
|
|
188
183
|
view.update_many("$unset" => Hash[fields])
|
|
189
184
|
end
|
|
190
185
|
|
data/lib/mongoid/copyable.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Mongoid
|
|
|
21
21
|
# @note This next line is here to address #2704, even though having an
|
|
22
22
|
# _id and id field in the document would cause problems with Mongoid
|
|
23
23
|
# elsewhere.
|
|
24
|
-
attrs = clone_document.except(
|
|
24
|
+
attrs = clone_document.except(*self.class.id_fields)
|
|
25
25
|
dynamic_attrs = {}
|
|
26
26
|
_attribute_names = self.attribute_names
|
|
27
27
|
attrs.reject! do |attr_name, value|
|
|
@@ -15,30 +15,6 @@ module Mongoid
|
|
|
15
15
|
|
|
16
16
|
private
|
|
17
17
|
|
|
18
|
-
# Expands the specified condition to MongoDB syntax.
|
|
19
|
-
#
|
|
20
|
-
# The condition must be a hash in one of the following forms:
|
|
21
|
-
# - {field_name: value}
|
|
22
|
-
# - {'field_name' => value}
|
|
23
|
-
# - {key_instance: value}
|
|
24
|
-
# - {'$operator' => operator_value_expression}
|
|
25
|
-
#
|
|
26
|
-
# This method expands the key instance form to the the operator form,
|
|
27
|
-
# and also converts hash key to string.
|
|
28
|
-
#
|
|
29
|
-
# The hash may contain multiple items, each representing a separate
|
|
30
|
-
# condition.
|
|
31
|
-
#
|
|
32
|
-
# @param [ Hash ] condition The condition to expand.
|
|
33
|
-
#
|
|
34
|
-
# @return [ Hash ] The expanded condition.
|
|
35
|
-
def expand_condition(condition)
|
|
36
|
-
mapped = condition.map do |field, value|
|
|
37
|
-
expand_one_condition(field, value)
|
|
38
|
-
end
|
|
39
|
-
Hash[mapped]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
18
|
# Expands the specified condition to MongoDB syntax.
|
|
43
19
|
#
|
|
44
20
|
# This method is meant to be called when processing the items of
|
|
@@ -227,7 +227,16 @@ module Mongoid
|
|
|
227
227
|
end
|
|
228
228
|
|
|
229
229
|
# Takes a criteria hash and expands Key objects into hashes containing
|
|
230
|
-
# MQL corresponding to said key objects.
|
|
230
|
+
# MQL corresponding to said key objects. Also converts the input to
|
|
231
|
+
# BSON::Document to permit indifferent access.
|
|
232
|
+
#
|
|
233
|
+
# The argument must be a hash containing key-value pairs of the
|
|
234
|
+
# following forms:
|
|
235
|
+
# - {field_name: value}
|
|
236
|
+
# - {'field_name' => value}
|
|
237
|
+
# - {key_instance: value}
|
|
238
|
+
# - {:$operator => operator_value_expression}
|
|
239
|
+
# - {'$operator' => operator_value_expression}
|
|
231
240
|
#
|
|
232
241
|
# Ruby does not permit multiple symbol operators. For example,
|
|
233
242
|
# {:foo.gt => 1, :foo.gt => 2} is collapsed to {:foo.gt => 2} by the
|
|
@@ -237,19 +246,23 @@ module Mongoid
|
|
|
237
246
|
# Similarly, this method should never need to expand a literal value
|
|
238
247
|
# and an operator at the same time.
|
|
239
248
|
#
|
|
249
|
+
# This method effectively converts symbol keys to string keys in
|
|
250
|
+
# the input +expr+, such that the downstream code can assume that
|
|
251
|
+
# conditions always contain string keys.
|
|
252
|
+
#
|
|
240
253
|
# @param [ Hash ] expr Criteria including Key instances.
|
|
241
254
|
#
|
|
242
|
-
# @return [
|
|
255
|
+
# @return [ BSON::Document ] The expanded criteria.
|
|
243
256
|
private def _mongoid_expand_keys(expr)
|
|
244
257
|
unless expr.is_a?(Hash)
|
|
245
258
|
raise ArgumentError, 'Argument must be a Hash'
|
|
246
259
|
end
|
|
247
260
|
|
|
248
|
-
result =
|
|
261
|
+
result = BSON::Document.new
|
|
249
262
|
expr.each do |field, value|
|
|
250
|
-
field.__expr_part__(value.__expand_complex__).each do |k, v|
|
|
251
|
-
if result[k]
|
|
252
|
-
if
|
|
263
|
+
field.__expr_part__(value.__expand_complex__, negating?).each do |k, v|
|
|
264
|
+
if existing = result[k]
|
|
265
|
+
if existing.is_a?(Hash)
|
|
253
266
|
# Existing value is an operator.
|
|
254
267
|
# If new value is also an operator, ensure there are no
|
|
255
268
|
# conflicts and add
|
|
@@ -257,8 +270,8 @@ module Mongoid
|
|
|
257
270
|
# The new value is also an operator.
|
|
258
271
|
# If there are no conflicts, combine the hashes, otherwise
|
|
259
272
|
# add new conditions to top level with $and.
|
|
260
|
-
if (v.keys &
|
|
261
|
-
|
|
273
|
+
if (v.keys & existing.keys).empty?
|
|
274
|
+
existing.update(v)
|
|
262
275
|
else
|
|
263
276
|
raise NotImplementedError, 'Ruby does not allow same symbol operator with different values'
|
|
264
277
|
result['$and'] ||= []
|
|
@@ -266,26 +279,39 @@ module Mongoid
|
|
|
266
279
|
end
|
|
267
280
|
else
|
|
268
281
|
# The new value is a simple value.
|
|
269
|
-
#
|
|
270
|
-
#
|
|
271
|
-
#
|
|
272
|
-
#
|
|
273
|
-
|
|
282
|
+
# Transform the implicit equality to either $eq or $regexp
|
|
283
|
+
# depending on the type of the argument. See
|
|
284
|
+
# https://docs.mongodb.com/manual/reference/operator/query/eq/#std-label-eq-usage-examples
|
|
285
|
+
# for the description of relevant server behavior.
|
|
286
|
+
op = case v
|
|
287
|
+
when Regexp, BSON::Regexp::Raw
|
|
288
|
+
'$regex'
|
|
289
|
+
else
|
|
290
|
+
'$eq'
|
|
291
|
+
end
|
|
292
|
+
# If there isn't an $eq/$regex operator already in the
|
|
293
|
+
# query, transform the new value into an operator
|
|
294
|
+
# expression and add it to the existing hash. Otherwise
|
|
295
|
+
# add the new condition with $and to the top level.
|
|
296
|
+
if existing.key?(op)
|
|
274
297
|
raise NotImplementedError, 'Ruby does not allow same symbol operator with different values'
|
|
275
298
|
result['$and'] ||= []
|
|
276
299
|
result['$and'] << {k => v}
|
|
277
300
|
else
|
|
278
|
-
|
|
301
|
+
existing.update(op => v)
|
|
279
302
|
end
|
|
280
303
|
end
|
|
281
304
|
else
|
|
282
305
|
# Existing value is a simple value.
|
|
283
|
-
#
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
306
|
+
# See the notes above about transformations to $eq/$regex.
|
|
307
|
+
op = case existing
|
|
308
|
+
when Regexp, BSON::Regexp::Raw
|
|
309
|
+
'$regex'
|
|
310
|
+
else
|
|
311
|
+
'$eq'
|
|
312
|
+
end
|
|
313
|
+
if v.is_a?(Hash) && !v.key?(op)
|
|
314
|
+
result[k] = {op => existing}.update(v)
|
|
289
315
|
else
|
|
290
316
|
raise NotImplementedError, 'Ruby does not allow same symbol operator with different values'
|
|
291
317
|
result['$and'] ||= []
|