mongoid 7.2.0 → 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/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/projector.rb +120 -0
- data/lib/mongoid/attributes.rb +32 -14
- 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.rb +19 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
- 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 +8 -8
- data/lib/mongoid/criteria/queryable/selector.rb +0 -4
- data/lib/mongoid/criteria.rb +4 -5
- data/lib/mongoid/document.rb +4 -17
- 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/interceptable.rb +3 -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/elem_match.rb +2 -1
- data/lib/mongoid/matcher/expression.rb +9 -14
- data/lib/mongoid/matcher/field_expression.rb +4 -5
- data/lib/mongoid/matcher/field_operator.rb +13 -11
- data/lib/mongoid/matcher/mod.rb +17 -0
- data/lib/mongoid/matcher/type.rb +99 -0
- data/lib/mongoid/matcher.rb +26 -43
- 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/reloadable.rb +5 -0
- 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/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
- data/spec/integration/app_spec.rb +171 -84
- data/spec/integration/associations/embeds_many_spec.rb +44 -0
- data/spec/integration/associations/has_one_spec.rb +48 -0
- data/spec/integration/callbacks_models.rb +49 -0
- data/spec/integration/callbacks_spec.rb +216 -0
- data/spec/integration/criteria/date_field_spec.rb +1 -1
- data/spec/integration/document_spec.rb +30 -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/elem_match.yml +46 -0
- data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
- data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
- data/spec/integration/matcher_operator_data/in.yml +16 -0
- data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
- data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/mod.yml +55 -0
- data/spec/integration/matcher_operator_data/ne_types.yml +15 -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 +5 -4
- data/spec/mongoid/association/depending_spec.rb +391 -352
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
- 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 +105 -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 +333 -0
- data/spec/mongoid/clients/factory_spec.rb +48 -0
- data/spec/mongoid/config_spec.rb +32 -0
- data/spec/mongoid/contextual/atomic_spec.rb +17 -4
- 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 +265 -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_fields_spec.rb +26 -0
- 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/matcher/extract_attribute_data/numeric_keys.yml +104 -0
- data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
- data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
- 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/settable_spec.rb +30 -0
- 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/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/lib/mrss/cluster_config.rb +221 -0
- data/spec/shared/lib/mrss/constraints.rb +51 -0
- data/spec/shared/lib/mrss/docker_runner.rb +265 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +14 -1
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +231 -0
- data/spec/shared/shlib/distro.sh +73 -0
- data/spec/shared/shlib/server.sh +290 -0
- data/spec/shared/shlib/set_env.sh +128 -0
- 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/customer.rb +11 -0
- data/spec/support/models/customer_address.rb +12 -0
- data/spec/support/models/dictionary.rb +6 -0
- data/spec/support/models/hole.rb +13 -0
- data/spec/support/models/mop.rb +9 -0
- 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
- data/spec/support/spec_config.rb +8 -0
- data.tar.gz.sig +0 -0
- metadata +146 -14
- metadata.gz.sig +5 -2
- data/spec/support/cluster_config.rb +0 -158
data/lib/mongoid/document.rb
CHANGED
|
@@ -151,7 +151,7 @@ module Mongoid
|
|
|
151
151
|
#
|
|
152
152
|
# @since 2.4.0
|
|
153
153
|
def to_key
|
|
154
|
-
(persisted? || destroyed?) ? [
|
|
154
|
+
(persisted? || destroyed?) ? [ _id.to_s ] : nil
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
# Return an array with this +Document+ only in it.
|
|
@@ -229,8 +229,9 @@ module Mongoid
|
|
|
229
229
|
became = klass.new(clone_document)
|
|
230
230
|
became._id = _id
|
|
231
231
|
became.instance_variable_set(:@changed_attributes, changed_attributes)
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
new_errors = ActiveModel::Errors.new(became)
|
|
233
|
+
new_errors.copy!(errors)
|
|
234
|
+
became.instance_variable_set(:@errors, new_errors)
|
|
234
235
|
became.instance_variable_set(:@new_record, new_record?)
|
|
235
236
|
became.instance_variable_set(:@destroyed, destroyed?)
|
|
236
237
|
became.changed_attributes[klass.discriminator_key] = self.class.discriminator_value
|
|
@@ -272,20 +273,6 @@ module Mongoid
|
|
|
272
273
|
@model_cache_key ||= self.class.model_name.cache_key
|
|
273
274
|
end
|
|
274
275
|
|
|
275
|
-
# Implement this for calls to flatten on array.
|
|
276
|
-
#
|
|
277
|
-
# @example Get the document as an array.
|
|
278
|
-
# document.to_ary
|
|
279
|
-
#
|
|
280
|
-
# @return [ nil ] Always nil.
|
|
281
|
-
#
|
|
282
|
-
# @since 2.1.0
|
|
283
|
-
def to_ary
|
|
284
|
-
nil
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
private
|
|
288
|
-
|
|
289
276
|
def as_attributes
|
|
290
277
|
return attributes if frozen?
|
|
291
278
|
embedded_relations.each_pair do |name, meta|
|
|
@@ -4,24 +4,23 @@
|
|
|
4
4
|
module Mongoid
|
|
5
5
|
module Errors
|
|
6
6
|
|
|
7
|
-
# This error is raised when
|
|
8
|
-
#
|
|
7
|
+
# This error is raised when attempting to destroy a model which has
|
|
8
|
+
# an association with dependency option set to restrict.
|
|
9
9
|
class DeleteRestriction < MongoidError
|
|
10
10
|
|
|
11
11
|
# Create the new callbacks error.
|
|
12
12
|
#
|
|
13
|
-
# @
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# @param [ Symbol ] association
|
|
13
|
+
# @param [ Document ] document The document that was attempted to be
|
|
14
|
+
# destroyed.
|
|
15
|
+
# @param [ Symbol ] association_name The name of the dependent
|
|
16
|
+
# association that prevents the document from being deleted.
|
|
18
17
|
#
|
|
19
18
|
# @since 3.0.0
|
|
20
|
-
def initialize(document,
|
|
19
|
+
def initialize(document, association_name)
|
|
21
20
|
super(
|
|
22
21
|
compose_message(
|
|
23
22
|
"delete_restriction",
|
|
24
|
-
{ document: document.class, relation:
|
|
23
|
+
{ document: document.class, relation: association_name }
|
|
25
24
|
)
|
|
26
25
|
)
|
|
27
26
|
end
|
data/lib/mongoid/evolvable.rb
CHANGED
|
@@ -117,7 +117,7 @@ module Mongoid
|
|
|
117
117
|
#
|
|
118
118
|
# @since 3.0.2
|
|
119
119
|
def delete_id
|
|
120
|
-
delete("_id") || delete(
|
|
120
|
+
delete("_id") || delete(:_id) || delete("id") || delete(:id)
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
# Get the id attribute from this hash, whether it's prefixed with an
|
|
@@ -130,7 +130,7 @@ module Mongoid
|
|
|
130
130
|
#
|
|
131
131
|
# @since 2.3.2
|
|
132
132
|
def extract_id
|
|
133
|
-
self["_id"] || self[
|
|
133
|
+
self["_id"] || self[:_id] || self["id"] || self[:id]
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
# Fetch a nested value via dot syntax.
|
data/lib/mongoid/fields.rb
CHANGED
|
@@ -13,6 +13,7 @@ module Mongoid
|
|
|
13
13
|
extend ActiveSupport::Concern
|
|
14
14
|
|
|
15
15
|
StringifiedSymbol = Mongoid::StringifiedSymbol
|
|
16
|
+
Boolean = Mongoid::Boolean
|
|
16
17
|
|
|
17
18
|
# For fields defined with symbols use the correct class.
|
|
18
19
|
#
|
|
@@ -37,10 +38,48 @@ module Mongoid
|
|
|
37
38
|
time: Time
|
|
38
39
|
}.with_indifferent_access
|
|
39
40
|
|
|
40
|
-
# Constant for all names of the
|
|
41
|
+
# Constant for all names of the _id field in a document.
|
|
41
42
|
#
|
|
42
|
-
#
|
|
43
|
-
|
|
43
|
+
# This does not include aliases of _id field.
|
|
44
|
+
#
|
|
45
|
+
# @api private
|
|
46
|
+
IDS = [ :_id, '_id', ].freeze
|
|
47
|
+
|
|
48
|
+
module ClassMethods
|
|
49
|
+
# Returns the list of id fields for this model class, as both strings
|
|
50
|
+
# and symbols.
|
|
51
|
+
#
|
|
52
|
+
# @return [ Array<Symbol | String> ] List of id fields.
|
|
53
|
+
#
|
|
54
|
+
# @api private
|
|
55
|
+
def id_fields
|
|
56
|
+
IDS.dup.tap do |id_fields|
|
|
57
|
+
aliased_fields.each do |k, v|
|
|
58
|
+
if v == '_id'
|
|
59
|
+
id_fields << k.to_sym
|
|
60
|
+
id_fields << k
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Extracts the id field from the specified attributes hash based on
|
|
67
|
+
# aliases defined in this class.
|
|
68
|
+
#
|
|
69
|
+
# @param [ Hash ] attributes The attributes to inspect.
|
|
70
|
+
#
|
|
71
|
+
# @return [ Object ] The id value.
|
|
72
|
+
#
|
|
73
|
+
# @api private
|
|
74
|
+
def extract_id_field(attributes)
|
|
75
|
+
id_fields.each do |k|
|
|
76
|
+
if v = attributes[k]
|
|
77
|
+
return v
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
44
83
|
|
|
45
84
|
included do
|
|
46
85
|
class_attribute :aliased_fields
|
|
@@ -62,8 +101,7 @@ module Mongoid
|
|
|
62
101
|
type: BSON::ObjectId
|
|
63
102
|
)
|
|
64
103
|
|
|
65
|
-
|
|
66
|
-
alias :id= :_id=
|
|
104
|
+
alias_attribute(:id, :_id)
|
|
67
105
|
end
|
|
68
106
|
|
|
69
107
|
# Apply all default values to the document which are not procs.
|
data/lib/mongoid/inspectable.rb
CHANGED
|
@@ -234,9 +234,11 @@ module Mongoid
|
|
|
234
234
|
# document.halted_callback_hook(filter)
|
|
235
235
|
#
|
|
236
236
|
# @param [ Symbol ] filter The callback that halted.
|
|
237
|
+
# @param [ Symbol ] name The name of the callback that was halted
|
|
238
|
+
# (requires Rails 6.1+)
|
|
237
239
|
#
|
|
238
240
|
# @since 3.0.3
|
|
239
|
-
def halted_callback_hook(filter)
|
|
241
|
+
def halted_callback_hook(filter, name = nil)
|
|
240
242
|
@before_callback_halted = true
|
|
241
243
|
end
|
|
242
244
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module Bits
|
|
6
|
+
def matches?(exists, value, condition)
|
|
7
|
+
case value
|
|
8
|
+
when BSON::Binary
|
|
9
|
+
value = value.data.split('').map { |n| '%02x' % n.ord }.join.to_i(16)
|
|
10
|
+
end
|
|
11
|
+
case condition
|
|
12
|
+
when Array
|
|
13
|
+
array_matches?(value, condition)
|
|
14
|
+
when BSON::Binary
|
|
15
|
+
int_cond = condition.data.split('').map { |n| '%02x' % n.ord }.join.to_i(16)
|
|
16
|
+
int_matches?(value, int_cond)
|
|
17
|
+
when Integer
|
|
18
|
+
if condition < 0
|
|
19
|
+
raise Errors::InvalidQuery, "Invalid value for $#{operator_name} argument: negative integers are not allowed: #{condition}"
|
|
20
|
+
end
|
|
21
|
+
int_matches?(value, condition)
|
|
22
|
+
when Float
|
|
23
|
+
if (int_cond = condition.to_i).to_f == condition
|
|
24
|
+
if int_cond < 0
|
|
25
|
+
raise Errors::InvalidQuery, "Invalid value for $#{operator_name} argument: negative numbers are not allowed: #{condition}"
|
|
26
|
+
end
|
|
27
|
+
int_matches?(value, int_cond)
|
|
28
|
+
else
|
|
29
|
+
raise Errors::InvalidQuery, "Invalid type for $#{operator_name} argument: not representable as an integer: #{condition}"
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
raise Errors::InvalidQuery, "Invalid type for $#{operator_name} argument: #{condition}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module_function def operator_name
|
|
37
|
+
name.sub(/.*::/, '').sub(/\A(.)/) { |l| l.downcase }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Mongoid
|
|
2
|
+
module Matcher
|
|
3
|
+
|
|
4
|
+
# @api private
|
|
5
|
+
module BitsAllClear
|
|
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 == 0
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -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
|
|
@@ -15,7 +15,8 @@ module Mongoid
|
|
|
15
15
|
# Validate the condition is valid, even though we will never attempt
|
|
16
16
|
# matching it.
|
|
17
17
|
condition.each do |k, v|
|
|
18
|
-
|
|
18
|
+
k = k.to_s
|
|
19
|
+
if k.start_with?('$')
|
|
19
20
|
begin
|
|
20
21
|
ExpressionOperator.get(k)
|
|
21
22
|
rescue Mongoid::Errors::InvalidExpressionOperator
|
|
@@ -12,25 +12,20 @@ module Mongoid
|
|
|
12
12
|
end
|
|
13
13
|
expr.all? do |k, expr_v|
|
|
14
14
|
k = k.to_s
|
|
15
|
+
if k == "$comment"
|
|
16
|
+
# Nothing
|
|
17
|
+
return true
|
|
18
|
+
end
|
|
15
19
|
if k.start_with?('$')
|
|
16
20
|
ExpressionOperator.get(k).matches?(document, expr_v)
|
|
17
21
|
else
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# Do not treat a hash as an array here (both are iterable).
|
|
23
|
-
if expanded && Array === value
|
|
24
|
-
if value == []
|
|
25
|
-
# Empty array is technically equivalent to exists: false.
|
|
26
|
-
FieldExpression.matches?(false, nil, expr_v)
|
|
27
|
-
else
|
|
28
|
-
value.any? do |v|
|
|
29
|
-
FieldExpression.matches?(true, v, expr_v)
|
|
30
|
-
end
|
|
22
|
+
values = Matcher.extract_attribute(document, k)
|
|
23
|
+
if values.length > 0
|
|
24
|
+
values.any? do |v|
|
|
25
|
+
FieldExpression.matches?(true, v, expr_v)
|
|
31
26
|
end
|
|
32
27
|
else
|
|
33
|
-
FieldExpression.matches?(
|
|
28
|
+
FieldExpression.matches?(false, nil, expr_v)
|
|
34
29
|
end
|
|
35
30
|
end
|
|
36
31
|
end
|
|
@@ -36,14 +36,13 @@ module Mongoid
|
|
|
36
36
|
FieldOperator.get(k).matches?(exists, value, cond_v)
|
|
37
37
|
end
|
|
38
38
|
elsif Hash === value
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
sub_value.any? do |sub_v|
|
|
39
|
+
sub_values = Matcher.extract_attribute(value, k)
|
|
40
|
+
if sub_values.length > 0
|
|
41
|
+
sub_values.any? do |sub_v|
|
|
43
42
|
Eq.matches?(true, sub_v, cond_v)
|
|
44
43
|
end
|
|
45
44
|
else
|
|
46
|
-
Eq.matches?(
|
|
45
|
+
Eq.matches?(false, nil, cond_v)
|
|
47
46
|
end
|
|
48
47
|
else
|
|
49
48
|
false
|
|
@@ -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)
|
|
@@ -35,17 +41,13 @@ module Mongoid
|
|
|
35
41
|
end
|
|
36
42
|
|
|
37
43
|
module_function def apply_comparison_operator(operator, left, right)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
false
|
|
48
|
-
end
|
|
44
|
+
left.send(operator, right)
|
|
45
|
+
rescue ArgumentError, NoMethodError, TypeError
|
|
46
|
+
# We silence bogus comparison attempts, e.g. number to string
|
|
47
|
+
# comparisons.
|
|
48
|
+
# Several different exceptions may be produced depending on the types
|
|
49
|
+
# involved.
|
|
50
|
+
false
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
end
|
|
@@ -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
|