mongoid 7.0.0.beta → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/config/locales/en.yml +21 -0
- data/lib/mongoid.rb +1 -1
- data/lib/mongoid/association/embedded/batchable.rb +39 -13
- data/lib/mongoid/association/many.rb +4 -0
- data/lib/mongoid/association/referenced/has_many.rb +2 -0
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +38 -7
- data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -2
- data/lib/mongoid/association/referenced/syncable.rb +1 -1
- data/lib/mongoid/association/touchable.rb +1 -1
- data/lib/mongoid/atomic.rb +3 -3
- data/lib/mongoid/atomic/modifiers.rb +12 -8
- data/lib/mongoid/attributes.rb +20 -12
- data/lib/mongoid/attributes/dynamic.rb +2 -2
- data/lib/mongoid/changeable.rb +1 -1
- data/lib/mongoid/clients.rb +2 -0
- data/lib/mongoid/clients/sessions.rb +113 -0
- data/lib/mongoid/clients/storage_options.rb +1 -0
- data/lib/mongoid/composable.rb +1 -0
- data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
- data/lib/mongoid/contextual/atomic.rb +6 -3
- data/lib/mongoid/contextual/geo_near.rb +1 -1
- data/lib/mongoid/contextual/map_reduce.rb +6 -2
- data/lib/mongoid/contextual/memory.rb +25 -2
- data/lib/mongoid/contextual/mongo.rb +33 -14
- data/lib/mongoid/copyable.rb +2 -2
- data/lib/mongoid/criteria.rb +1 -0
- data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +3 -1
- data/lib/mongoid/errors.rb +1 -0
- data/lib/mongoid/errors/invalid_session_use.rb +24 -0
- data/lib/mongoid/extensions.rb +0 -4
- data/lib/mongoid/extensions/hash.rb +5 -2
- data/lib/mongoid/factory.rb +14 -5
- data/lib/mongoid/fields.rb +2 -2
- data/lib/mongoid/indexable.rb +4 -4
- data/lib/mongoid/matchable/and.rb +1 -1
- data/lib/mongoid/matchable/elem_match.rb +9 -3
- data/lib/mongoid/persistable.rb +2 -2
- data/lib/mongoid/persistable/creatable.rb +4 -2
- data/lib/mongoid/persistable/deletable.rb +4 -2
- data/lib/mongoid/persistable/destroyable.rb +1 -5
- data/lib/mongoid/persistable/updatable.rb +2 -2
- data/lib/mongoid/persistable/upsertable.rb +2 -1
- data/lib/mongoid/persistence_context.rb +5 -4
- data/lib/mongoid/query_cache.rb +5 -3
- data/lib/mongoid/reloadable.rb +1 -1
- data/lib/mongoid/serializable.rb +1 -1
- data/lib/mongoid/shardable.rb +1 -1
- data/lib/mongoid/tasks/database.rb +3 -2
- data/lib/mongoid/threaded.rb +38 -0
- data/lib/mongoid/traversable.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -0
- data/spec/app/models/band.rb +1 -0
- data/spec/app/models/shipment_address.rb +1 -0
- data/spec/mongoid/association/macros_spec.rb +20 -0
- data/spec/mongoid/association/referenced/has_many/eager_spec.rb +15 -0
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +229 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
- data/spec/mongoid/atomic_spec.rb +17 -17
- data/spec/mongoid/attributes_spec.rb +38 -2
- data/spec/mongoid/clients/sessions_spec.rb +325 -0
- data/spec/mongoid/contextual/memory_spec.rb +19 -0
- data/spec/mongoid/contextual/mongo_spec.rb +133 -0
- data/spec/mongoid/copyable_spec.rb +34 -0
- data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +43 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +32 -3
- data/spec/mongoid/extensions/hash_spec.rb +18 -1
- data/spec/mongoid/factory_spec.rb +11 -0
- data/spec/mongoid/interceptable_spec.rb +3 -1
- data/spec/mongoid/matchable/elem_match_spec.rb +20 -0
- data/spec/mongoid/persistable/deletable_spec.rb +19 -0
- data/spec/mongoid/persistable/destroyable_spec.rb +19 -0
- data/spec/mongoid/persistable/savable_spec.rb +2 -2
- data/spec/mongoid/persistable/updatable_spec.rb +2 -2
- data/spec/mongoid/persistable_spec.rb +31 -16
- data/spec/mongoid/persistence_context_spec.rb +14 -0
- data/spec/mongoid/positional_spec.rb +10 -10
- data/spec/mongoid/query_cache_spec.rb +2 -16
- data/spec/mongoid/shardable_spec.rb +32 -12
- data/spec/spec_helper.rb +74 -0
- metadata +456 -446
- metadata.gz.sig +0 -0
@@ -259,7 +259,9 @@ module Mongoid
|
|
259
259
|
def prepare(field, operator, value)
|
260
260
|
unless operator =~ /exists|type|size/
|
261
261
|
value = value.__expand_complex__
|
262
|
-
|
262
|
+
field = field.to_s
|
263
|
+
name = aliases[field] || field
|
264
|
+
serializer = serializers[name]
|
263
265
|
value = serializer ? serializer.evolve(value) : value
|
264
266
|
end
|
265
267
|
selection = { operator => value }
|
data/lib/mongoid/errors.rb
CHANGED
@@ -20,6 +20,7 @@ require "mongoid/errors/invalid_persistence_option"
|
|
20
20
|
require "mongoid/errors/invalid_relation"
|
21
21
|
require "mongoid/errors/invalid_relation_option"
|
22
22
|
require "mongoid/errors/invalid_scope"
|
23
|
+
require "mongoid/errors/invalid_session_use"
|
23
24
|
require "mongoid/errors/invalid_set_polymorphic_relation"
|
24
25
|
require "mongoid/errors/invalid_storage_options"
|
25
26
|
require "mongoid/errors/invalid_storage_parent"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Errors
|
4
|
+
|
5
|
+
# This error is raised when a session is attempted to be used with a model whose client cannot use it, if
|
6
|
+
# sessions are nested, or if the mongodb deployment doesn't support sessions.
|
7
|
+
#
|
8
|
+
# @since 6.4.0
|
9
|
+
class InvalidSessionUse < MongoidError
|
10
|
+
|
11
|
+
# Create the error.
|
12
|
+
#
|
13
|
+
# @example Create the error.
|
14
|
+
# InvalidSessionUse.new(:invalid_session_use)
|
15
|
+
#
|
16
|
+
# @param [ :invalid_sesion_use, :invalid_session_nesting ] error_type The type of session misuse.
|
17
|
+
#
|
18
|
+
# @since 6.4.0
|
19
|
+
def initialize(error_type)
|
20
|
+
super(compose_message(error_type.to_s))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/mongoid/extensions.rb
CHANGED
@@ -5,10 +5,6 @@ class BSON::ObjectId
|
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
-
class Symbol
|
9
|
-
remove_method :size if instance_methods.include? :size # temporal fix for ruby 1.9
|
10
|
-
end
|
11
|
-
|
12
8
|
class BSON::Document
|
13
9
|
# We need to override this as ActiveSupport creates a new Object, instead of a new Hash
|
14
10
|
# see https://github.com/rails/rails/commit/f1bad130d0c9bd77c94e43b696adca56c46a66aa
|
@@ -106,8 +106,11 @@ module Mongoid
|
|
106
106
|
value = self
|
107
107
|
keys.each do |key|
|
108
108
|
return nil if value.nil?
|
109
|
-
|
110
|
-
|
109
|
+
value_for_key = value[key]
|
110
|
+
if value_for_key.nil? && key.to_i.to_s == key
|
111
|
+
value_for_key = value[key.to_i]
|
112
|
+
end
|
113
|
+
value = value_for_key
|
111
114
|
end
|
112
115
|
value
|
113
116
|
end
|
data/lib/mongoid/factory.rb
CHANGED
@@ -17,7 +17,8 @@ module Mongoid
|
|
17
17
|
#
|
18
18
|
# @return [ Document ] The instantiated document.
|
19
19
|
def build(klass, attributes = nil)
|
20
|
-
|
20
|
+
attributes ||= {}
|
21
|
+
type = attributes[TYPE] || attributes[TYPE.to_sym]
|
21
22
|
if type && klass._types.include?(type)
|
22
23
|
type.constantize.new(attributes)
|
23
24
|
else
|
@@ -37,14 +38,22 @@ module Mongoid
|
|
37
38
|
# #only we give the document a list of the selected fields.
|
38
39
|
#
|
39
40
|
# @return [ Document ] The instantiated document.
|
40
|
-
def from_db(klass, attributes = nil,
|
41
|
+
def from_db(klass, attributes = nil, criteria = nil)
|
42
|
+
selected_fields = criteria.options[:fields] if criteria
|
41
43
|
type = (attributes || {})[TYPE]
|
42
44
|
if type.blank?
|
43
|
-
klass.instantiate(attributes, selected_fields)
|
45
|
+
obj = klass.instantiate(attributes, selected_fields)
|
46
|
+
if criteria && criteria.association && criteria.parent_document
|
47
|
+
obj.set_relation(criteria.association.inverse, criteria.parent_document)
|
48
|
+
end
|
49
|
+
obj
|
44
50
|
else
|
45
51
|
camelized = type.camelize
|
46
|
-
|
47
|
-
|
52
|
+
begin
|
53
|
+
camelized.constantize.instantiate(attributes, selected_fields)
|
54
|
+
rescue NameError
|
55
|
+
raise Errors::UnknownModel.new(camelized, type)
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
50
59
|
end
|
data/lib/mongoid/fields.rb
CHANGED
@@ -411,7 +411,7 @@ module Mongoid
|
|
411
411
|
def create_field_getter(name, meth, field)
|
412
412
|
generated_methods.module_eval do
|
413
413
|
re_define_method(meth) do
|
414
|
-
raw =
|
414
|
+
raw = read_raw_attribute(name)
|
415
415
|
if lazy_settable?(field, raw)
|
416
416
|
write_attribute(name, field.eval_default(self))
|
417
417
|
else
|
@@ -480,7 +480,7 @@ module Mongoid
|
|
480
480
|
def create_field_check(name, meth)
|
481
481
|
generated_methods.module_eval do
|
482
482
|
re_define_method("#{meth}?") do
|
483
|
-
value =
|
483
|
+
value = read_raw_attribute(name)
|
484
484
|
lookup_attribute_presence(name, value)
|
485
485
|
end
|
486
486
|
end
|
data/lib/mongoid/indexable.rb
CHANGED
@@ -35,10 +35,10 @@ module Mongoid
|
|
35
35
|
key, options = spec.key, default_options.merge(spec.options)
|
36
36
|
if database = options[:database]
|
37
37
|
with(database: database) do |klass|
|
38
|
-
klass.collection.indexes.create_one(key, options.except(:database))
|
38
|
+
klass.collection.indexes(session: session).create_one(key, options.except(:database))
|
39
39
|
end
|
40
40
|
else
|
41
|
-
collection.indexes.create_one(key, options)
|
41
|
+
collection.indexes(session: session).create_one(key, options)
|
42
42
|
end
|
43
43
|
end and true
|
44
44
|
end
|
@@ -56,9 +56,9 @@ module Mongoid
|
|
56
56
|
indexed_database_names.each do |database|
|
57
57
|
with(database: database) do |klass|
|
58
58
|
begin
|
59
|
-
klass.collection.indexes.each do |spec|
|
59
|
+
klass.collection.indexes(session: session).each do |spec|
|
60
60
|
unless spec["name"] == "_id_"
|
61
|
-
klass.collection.indexes.drop_one(spec["key"])
|
61
|
+
klass.collection.indexes(session: session).drop_one(spec["key"])
|
62
62
|
logger.info(
|
63
63
|
"MONGOID: Removed index '#{spec["name"]}' on collection " +
|
64
64
|
"'#{klass.collection.name}' in database '#{database}'."
|
@@ -13,13 +13,19 @@ module Mongoid
|
|
13
13
|
#
|
14
14
|
# @return [ true, false ] If the values match.
|
15
15
|
def _matches?(value)
|
16
|
-
|
16
|
+
elem_match = value["$elemMatch"] || value[:$elemMatch]
|
17
|
+
|
18
|
+
if !@attribute.is_a?(Array) || !value.kind_of?(Hash) || !elem_match.kind_of?(Hash)
|
17
19
|
return false
|
18
20
|
end
|
19
21
|
|
20
22
|
return @attribute.any? do |sub_document|
|
21
|
-
|
22
|
-
|
23
|
+
elem_match.all? do |k, v|
|
24
|
+
if v.try(:first).try(:[],0) == "$not".freeze || v.try(:first).try(:[],0) == :$not
|
25
|
+
!Matchable.matcher(sub_document, k, v.first[1])._matches?(v.first[1])
|
26
|
+
else
|
27
|
+
Matchable.matcher(sub_document, k, v)._matches?(v)
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
data/lib/mongoid/persistable.rb
CHANGED
@@ -201,9 +201,9 @@ module Mongoid
|
|
201
201
|
#
|
202
202
|
# @since 4.0.0
|
203
203
|
def persist_atomic_operations(operations)
|
204
|
-
if persisted? && operations
|
204
|
+
if persisted? && operations && !operations.empty?
|
205
205
|
selector = atomic_selector
|
206
|
-
_root.collection.find(selector).update_one(positionally(selector, operations))
|
206
|
+
_root.collection.find(selector).update_one(positionally(selector, operations), session: session)
|
207
207
|
end
|
208
208
|
end
|
209
209
|
end
|
@@ -61,7 +61,9 @@ module Mongoid
|
|
61
61
|
_parent.insert
|
62
62
|
else
|
63
63
|
selector = _parent.atomic_selector
|
64
|
-
_root.collection.find(selector).update_one(
|
64
|
+
_root.collection.find(selector).update_one(
|
65
|
+
positionally(selector, atomic_inserts),
|
66
|
+
session: session)
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
@@ -76,7 +78,7 @@ module Mongoid
|
|
76
78
|
#
|
77
79
|
# @since 4.0.0
|
78
80
|
def insert_as_root
|
79
|
-
collection.insert_one(as_attributes)
|
81
|
+
collection.insert_one(as_attributes, session: session)
|
80
82
|
end
|
81
83
|
|
82
84
|
# Post process an insert, which sets the new record attribute to false
|
@@ -64,7 +64,9 @@ module Mongoid
|
|
64
64
|
_parent.remove_child(self) if notifying_parent?(options)
|
65
65
|
if _parent.persisted?
|
66
66
|
selector = _parent.atomic_selector
|
67
|
-
_root.collection.find(selector).update_one(
|
67
|
+
_root.collection.find(selector).update_one(
|
68
|
+
positionally(selector, atomic_deletes),
|
69
|
+
session: session)
|
68
70
|
end
|
69
71
|
true
|
70
72
|
end
|
@@ -80,7 +82,7 @@ module Mongoid
|
|
80
82
|
#
|
81
83
|
# @since 4.0.0
|
82
84
|
def delete_as_root
|
83
|
-
collection.find(atomic_selector).delete_one
|
85
|
+
collection.find(atomic_selector).delete_one(session: session)
|
84
86
|
true
|
85
87
|
end
|
86
88
|
|
@@ -48,11 +48,7 @@ module Mongoid
|
|
48
48
|
#
|
49
49
|
# @since 1.0.0
|
50
50
|
def destroy_all(conditions = nil)
|
51
|
-
|
52
|
-
documents = where(selector)
|
53
|
-
destroyed = documents.count
|
54
|
-
documents.each { |doc| doc.destroy }
|
55
|
-
destroyed
|
51
|
+
where(conditions || {}).destroy
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
@@ -134,9 +134,9 @@ module Mongoid
|
|
134
134
|
unless updates.empty?
|
135
135
|
coll = collection(_root)
|
136
136
|
selector = atomic_selector
|
137
|
-
coll.find(selector).update_one(positionally(selector, updates))
|
137
|
+
coll.find(selector).update_one(positionally(selector, updates), session: session)
|
138
138
|
conflicts.each_pair do |key, value|
|
139
|
-
coll.find(selector).update_one(positionally(selector, { key => value }))
|
139
|
+
coll.find(selector).update_one(positionally(selector, { key => value }), session: session)
|
140
140
|
end
|
141
141
|
end
|
142
142
|
end
|
@@ -21,7 +21,8 @@ module Mongoid
|
|
21
21
|
# @since 3.0.0
|
22
22
|
def upsert(options = {})
|
23
23
|
prepare_upsert(options) do
|
24
|
-
collection.find(atomic_selector).update_one(
|
24
|
+
collection.find(atomic_selector).update_one(
|
25
|
+
as_attributes, upsert: true, session: session)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -195,10 +195,10 @@ module Mongoid
|
|
195
195
|
Thread.current["[mongoid][#{object.object_id}]:context"]
|
196
196
|
end
|
197
197
|
|
198
|
-
#
|
198
|
+
# Clear the persistence context for a particular class or model instance.
|
199
199
|
#
|
200
|
-
# @example
|
201
|
-
# PersistenceContext.
|
200
|
+
# @example Clear the persistence context for a class or model instance.
|
201
|
+
# PersistenceContext.clear(model)
|
202
202
|
#
|
203
203
|
# @param [ Class, Object ] object The class or model instance.
|
204
204
|
# @param [ Mongo::Cluster ] cluster The original cluster before this context was used.
|
@@ -208,8 +208,9 @@ module Mongoid
|
|
208
208
|
if context = get(object)
|
209
209
|
context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
|
210
210
|
end
|
211
|
+
ensure
|
211
212
|
Thread.current["[mongoid][#{object.object_id}]:context"] = nil
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end
|
215
|
-
end
|
216
|
+
end
|
data/lib/mongoid/query_cache.rb
CHANGED
@@ -222,9 +222,11 @@ module Mongoid
|
|
222
222
|
super
|
223
223
|
else
|
224
224
|
unless cursor = cached_cursor
|
225
|
-
|
226
|
-
|
227
|
-
|
225
|
+
read_with_retry do
|
226
|
+
server = server_selector.select_server(cluster)
|
227
|
+
cursor = CachedCursor.new(view, send_initial_query(server), server)
|
228
|
+
QueryCache.cache_table[cache_key] = cursor
|
229
|
+
end
|
228
230
|
end
|
229
231
|
cursor.each do |doc|
|
230
232
|
yield doc
|
data/lib/mongoid/reloadable.rb
CHANGED
@@ -58,7 +58,7 @@ module Mongoid
|
|
58
58
|
#
|
59
59
|
# @since 2.3.2
|
60
60
|
def reload_root_document
|
61
|
-
{}.merge(collection.find(_id: _id).read(mode: :primary).first || {})
|
61
|
+
{}.merge(collection.find({ _id: _id }, session: session).read(mode: :primary).first || {})
|
62
62
|
end
|
63
63
|
|
64
64
|
# Reload the embedded document.
|
data/lib/mongoid/serializable.rb
CHANGED
@@ -101,7 +101,7 @@ module Mongoid
|
|
101
101
|
value = send(name)
|
102
102
|
attrs[name] = value ? value.serializable_hash(options) : nil
|
103
103
|
elsif names.include?(name) && !fields.key?(name)
|
104
|
-
attrs[name] =
|
104
|
+
attrs[name] = read_raw_attribute(name)
|
105
105
|
elsif !attribute_missing?(name)
|
106
106
|
attrs[name] = send(name)
|
107
107
|
end
|
data/lib/mongoid/shardable.rb
CHANGED
@@ -44,7 +44,7 @@ module Mongoid
|
|
44
44
|
models.each do |model|
|
45
45
|
unless model.embedded?
|
46
46
|
begin
|
47
|
-
model.collection.indexes.each do |index|
|
47
|
+
model.collection.indexes(session: model.send(:session)).each do |index|
|
48
48
|
# ignore default index
|
49
49
|
unless index['name'] == '_id_'
|
50
50
|
key = index['key'].symbolize_keys
|
@@ -77,7 +77,7 @@ module Mongoid
|
|
77
77
|
indexes.each do |index|
|
78
78
|
key = index['key'].symbolize_keys
|
79
79
|
collection = model.collection
|
80
|
-
collection.indexes.drop_one(key)
|
80
|
+
collection.indexes(session: model.send(:session)).drop_one(key)
|
81
81
|
logger.info(
|
82
82
|
"MONGOID: Removed index '#{index['name']}' on collection " +
|
83
83
|
"'#{collection.name}' in database '#{collection.database.name}'."
|
@@ -107,6 +107,7 @@ module Mongoid
|
|
107
107
|
end
|
108
108
|
|
109
109
|
private
|
110
|
+
|
110
111
|
def logger
|
111
112
|
Mongoid.logger
|
112
113
|
end
|
data/lib/mongoid/threaded.rb
CHANGED
@@ -325,5 +325,43 @@ module Mongoid
|
|
325
325
|
def validations_for(klass)
|
326
326
|
validations[klass] ||= []
|
327
327
|
end
|
328
|
+
|
329
|
+
# Cache a session for this thread.
|
330
|
+
#
|
331
|
+
# @example Save a session for this thread.
|
332
|
+
# Threaded.set_session(session)
|
333
|
+
#
|
334
|
+
# @param [ Mongo::Session ] session The session to save.
|
335
|
+
#
|
336
|
+
# @since 6.4.0
|
337
|
+
def set_session(session)
|
338
|
+
Thread.current[:session] = session
|
339
|
+
end
|
340
|
+
|
341
|
+
# Get the cached session for this thread.
|
342
|
+
#
|
343
|
+
# @example Get the session for this thread.
|
344
|
+
# Threaded.get_session
|
345
|
+
#
|
346
|
+
# @return [ Mongo::Session, nil ] The session cached on this thread or nil.
|
347
|
+
#
|
348
|
+
# @since 6.4.0
|
349
|
+
def get_session
|
350
|
+
Thread.current[:session]
|
351
|
+
end
|
352
|
+
|
353
|
+
# Clear the cached session for this thread.
|
354
|
+
#
|
355
|
+
# @example Clear this thread's session.
|
356
|
+
# Threaded.clear_session
|
357
|
+
#
|
358
|
+
# @return [ nil ]
|
359
|
+
#
|
360
|
+
# @since 6.4.0
|
361
|
+
def clear_session
|
362
|
+
session = get_session
|
363
|
+
session.end_session if session
|
364
|
+
Thread.current[:session] = nil
|
365
|
+
end
|
328
366
|
end
|
329
367
|
end
|
data/lib/mongoid/traversable.rb
CHANGED
data/lib/mongoid/version.rb
CHANGED
@@ -11,6 +11,10 @@ development:
|
|
11
11
|
hosts:
|
12
12
|
- localhost:27017
|
13
13
|
options:
|
14
|
+
# Note that all options listed below are Ruby driver client options (the mongo gem).
|
15
|
+
# Please refer to the driver documentation of the version of the mongo gem you are using
|
16
|
+
# for the most up-to-date list of options.
|
17
|
+
#
|
14
18
|
# Change the default write concern. (default = { w: 1 })
|
15
19
|
# write:
|
16
20
|
# w: 1
|