mongoid 2.3.5 → 2.4.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.
- data/CHANGELOG.md +34 -176
- data/LICENSE +1 -1
- data/lib/config/locales/bg.yml +6 -0
- data/lib/config/locales/de.yml +6 -0
- data/lib/config/locales/en-GB.yml +8 -0
- data/lib/config/locales/en.yml +8 -0
- data/lib/config/locales/es.yml +9 -3
- data/lib/config/locales/fr.yml +6 -0
- data/lib/config/locales/hi.yml +6 -0
- data/lib/config/locales/hu.yml +6 -0
- data/lib/config/locales/id.yml +6 -0
- data/lib/config/locales/it.yml +6 -0
- data/lib/config/locales/ja.yml +6 -0
- data/lib/config/locales/kr.yml +6 -0
- data/lib/config/locales/nl.yml +8 -0
- data/lib/config/locales/pl.yml +6 -0
- data/lib/config/locales/pt-BR.yml +6 -0
- data/lib/config/locales/pt.yml +8 -2
- data/lib/config/locales/ro.yml +6 -0
- data/lib/config/locales/ru.yml +6 -0
- data/lib/config/locales/sv.yml +6 -0
- data/lib/config/locales/vi.yml +14 -8
- data/lib/config/locales/zh-CN.yml +6 -0
- data/lib/mongoid/atomic.rb +62 -13
- data/lib/mongoid/atomic/modifiers.rb +33 -1
- data/lib/mongoid/attributes.rb +5 -19
- data/lib/mongoid/callbacks.rb +2 -1
- data/lib/mongoid/collection.rb +2 -2
- data/lib/mongoid/collections/retry.rb +18 -6
- data/lib/mongoid/components.rb +2 -0
- data/lib/mongoid/config.rb +8 -63
- data/lib/mongoid/config/environment.rb +41 -0
- data/lib/mongoid/config/options.rb +74 -0
- data/lib/mongoid/contexts/enumerable.rb +0 -24
- data/lib/mongoid/contexts/mongo.rb +33 -3
- data/lib/mongoid/copyable.rb +1 -1
- data/lib/mongoid/criteria.rb +4 -2
- data/lib/mongoid/criterion/inclusion.rb +1 -16
- data/lib/mongoid/criterion/optional.rb +37 -10
- data/lib/mongoid/criterion/scoping.rb +83 -0
- data/lib/mongoid/criterion/selector.rb +9 -6
- data/lib/mongoid/default_scope.rb +1 -1
- data/lib/mongoid/dirty.rb +163 -29
- data/lib/mongoid/document.rb +58 -7
- data/lib/mongoid/errors.rb +2 -0
- data/lib/mongoid/errors/no_environment.rb +19 -0
- data/lib/mongoid/errors/scope_overwrite.rb +21 -0
- data/lib/mongoid/extensions.rb +6 -0
- data/lib/mongoid/extensions/array/deep_copy.rb +25 -0
- data/lib/mongoid/extensions/hash/deep_copy.rb +25 -0
- data/lib/mongoid/extensions/hash/scoping.rb +1 -1
- data/lib/mongoid/extensions/object/deep_copy.rb +21 -0
- data/lib/mongoid/extensions/proc/scoping.rb +2 -2
- data/lib/mongoid/extensions/symbol/inflections.rb +1 -0
- data/lib/mongoid/fields.rb +171 -104
- data/lib/mongoid/fields/{serializable → internal}/array.rb +33 -1
- data/lib/mongoid/fields/{serializable → internal}/big_decimal.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/bignum.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/binary.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/boolean.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/date.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/date_time.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/fixnum.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/float.rb +16 -1
- data/lib/mongoid/fields/internal/foreign_keys/array.rb +74 -0
- data/lib/mongoid/fields/{serializable → internal}/foreign_keys/object.rb +11 -2
- data/lib/mongoid/fields/{serializable → internal}/hash.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/integer.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/localized.rb +23 -2
- data/lib/mongoid/fields/{serializable → internal}/nil_class.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/object.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/object_id.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/range.rb +21 -2
- data/lib/mongoid/fields/{serializable → internal}/set.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/string.rb +16 -1
- data/lib/mongoid/fields/{serializable → internal}/symbol.rb +17 -1
- data/lib/mongoid/fields/{serializable → internal}/time.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/time_with_zone.rb +1 -1
- data/lib/mongoid/fields/{serializable → internal}/timekeeping.rb +16 -1
- data/lib/mongoid/fields/mappings.rb +8 -3
- data/lib/mongoid/fields/serializable.rb +34 -3
- data/lib/mongoid/hierarchy.rb +14 -14
- data/lib/mongoid/identity_map.rb +3 -2
- data/lib/mongoid/logger.rb +1 -7
- data/lib/mongoid/named_scope.rb +16 -12
- data/lib/mongoid/observer.rb +5 -1
- data/lib/mongoid/paranoia.rb +1 -0
- data/lib/mongoid/persistence.rb +11 -4
- data/lib/mongoid/persistence/atomic.rb +4 -1
- data/lib/mongoid/persistence/atomic/add_to_set.rb +17 -1
- data/lib/mongoid/persistence/atomic/sets.rb +1 -1
- data/lib/mongoid/railties/database.rake +1 -1
- data/lib/mongoid/relations.rb +1 -3
- data/lib/mongoid/relations/auto_save.rb +1 -1
- data/lib/mongoid/relations/builders.rb +1 -1
- data/lib/mongoid/relations/builders/embedded/many.rb +2 -6
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +1 -1
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +1 -1
- data/lib/mongoid/relations/cascading/delete.rb +1 -1
- data/lib/mongoid/relations/cyclic.rb +10 -6
- data/lib/mongoid/relations/embedded/atomic.rb +3 -3
- data/lib/mongoid/relations/embedded/many.rb +98 -20
- data/lib/mongoid/relations/macros.rb +2 -0
- data/lib/mongoid/relations/many.rb +13 -0
- data/lib/mongoid/relations/metadata.rb +3 -3
- data/lib/mongoid/relations/nested_builder.rb +4 -3
- data/lib/mongoid/relations/proxy.rb +0 -1
- data/lib/mongoid/relations/referenced/batch.rb +3 -2
- data/lib/mongoid/relations/referenced/in.rb +3 -3
- data/lib/mongoid/relations/referenced/many.rb +89 -10
- data/lib/mongoid/relations/referenced/many_to_many.rb +34 -43
- data/lib/mongoid/relations/referenced/one.rb +8 -4
- data/lib/mongoid/relations/synchronization.rb +22 -5
- data/lib/mongoid/threaded.rb +38 -276
- data/lib/mongoid/threaded/lifecycle.rb +18 -18
- data/lib/mongoid/timestamps/updated.rb +13 -3
- data/lib/mongoid/validations.rb +22 -1
- data/lib/mongoid/validations/presence.rb +40 -0
- data/lib/mongoid/validations/uniqueness.rb +14 -3
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +6 -2
- data/lib/rails/mongoid.rb +7 -1
- metadata +64 -45
- data/lib/mongoid/fields/serializable/foreign_keys/array.rb +0 -42
- data/lib/mongoid/relations/embedded/sort.rb +0 -31
|
@@ -116,6 +116,19 @@ module Mongoid #:nodoc:
|
|
|
116
116
|
target.map { |document| document.serializable_hash(options) }
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
+
# Get a criteria for the embedded documents without the default scoping
|
|
120
|
+
# applied.
|
|
121
|
+
#
|
|
122
|
+
# @example Get the unscoped criteria.
|
|
123
|
+
# person.addresses.unscoped
|
|
124
|
+
#
|
|
125
|
+
# @return [ Criteria ] The unscoped criteria.
|
|
126
|
+
#
|
|
127
|
+
# @since 2.4.0
|
|
128
|
+
def unscoped
|
|
129
|
+
criteria.unscoped
|
|
130
|
+
end
|
|
131
|
+
|
|
119
132
|
private
|
|
120
133
|
|
|
121
134
|
# Find the first object given the supplied attributes or create/initialize it.
|
|
@@ -197,13 +197,13 @@ module Mongoid # :nodoc:
|
|
|
197
197
|
# @example Get the eager loading criteria.
|
|
198
198
|
# metadata.eager_load(criteria)
|
|
199
199
|
#
|
|
200
|
-
# @param [
|
|
200
|
+
# @param [ Array<Object> ] ids The ids of the returned parents.
|
|
201
201
|
#
|
|
202
202
|
# @return [ Criteria ] The eager loading criteria.
|
|
203
203
|
#
|
|
204
204
|
# @since 2.2.0
|
|
205
|
-
def eager_load(
|
|
206
|
-
relation.eager_load(self,
|
|
205
|
+
def eager_load(ids)
|
|
206
|
+
relation.eager_load(self, ids)
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
# Will determine if the relation is an embedded one or not. Currently
|
|
@@ -60,15 +60,16 @@ module Mongoid # :nodoc:
|
|
|
60
60
|
# @todo Durran: Move this into a common reusable place.
|
|
61
61
|
#
|
|
62
62
|
# @example Convert the id.
|
|
63
|
-
# builder.convert_id("4d371b444835d98b8b000010")
|
|
63
|
+
# builder.convert_id(Person, "4d371b444835d98b8b000010")
|
|
64
64
|
#
|
|
65
|
+
# @param [ Class ] klass The class we're trying to convert for.
|
|
65
66
|
# @param [ String ] id The id, usually coming from the form.
|
|
66
67
|
#
|
|
67
68
|
# @return [ BSON::ObjectId, String, Object ] The converted id.
|
|
68
69
|
#
|
|
69
70
|
# @since 2.0.0.rc.6
|
|
70
|
-
def convert_id(id)
|
|
71
|
-
|
|
71
|
+
def convert_id(klass, id)
|
|
72
|
+
BSON::ObjectId.convert(klass, id)
|
|
72
73
|
end
|
|
73
74
|
end
|
|
74
75
|
end
|
|
@@ -18,7 +18,6 @@ module Mongoid # :nodoc:
|
|
|
18
18
|
# Backwards compatibility with Mongoid beta releases.
|
|
19
19
|
delegate :klass, :to => :metadata
|
|
20
20
|
delegate :bind_one, :unbind_one, :to => :binding
|
|
21
|
-
delegate :collection_name, :to => :base
|
|
22
21
|
|
|
23
22
|
# Convenience for setting the target and the metadata properties since
|
|
24
23
|
# all proxies will need to do this.
|
|
@@ -38,11 +38,12 @@ module Mongoid #:nodoc:
|
|
|
38
38
|
#
|
|
39
39
|
# @since 2.0.2, batch-relational-insert
|
|
40
40
|
def batched(&block)
|
|
41
|
-
|
|
41
|
+
name = collection.name
|
|
42
|
+
inserter = Threaded.insert(name) || Threaded.set_insert(name, Insert.new)
|
|
42
43
|
count_executions(&block)
|
|
43
44
|
ensure
|
|
44
45
|
if @executions.zero?
|
|
45
|
-
Threaded.
|
|
46
|
+
Threaded.set_insert(name, nil)
|
|
46
47
|
inserter.execute(collection)
|
|
47
48
|
end
|
|
48
49
|
end
|
|
@@ -117,15 +117,15 @@ module Mongoid # :nodoc:
|
|
|
117
117
|
# Proxy.eager_load(metadata, criteria)
|
|
118
118
|
#
|
|
119
119
|
# @param [ Metadata ] metadata The relation metadata.
|
|
120
|
-
# @param [
|
|
120
|
+
# @param [ Array<Object> ] ids The ids of the target docs.
|
|
121
121
|
#
|
|
122
122
|
# @return [ Criteria ] The criteria to eager load the relation.
|
|
123
123
|
#
|
|
124
124
|
# @since 2.2.0
|
|
125
|
-
def eager_load(metadata,
|
|
125
|
+
def eager_load(metadata, ids)
|
|
126
126
|
raise Errors::EagerLoad.new(metadata.name) if metadata.polymorphic?
|
|
127
127
|
klass, foreign_key = metadata.klass, metadata.foreign_key
|
|
128
|
-
klass.any_in("_id" =>
|
|
128
|
+
klass.any_in("_id" => ids).each do |doc|
|
|
129
129
|
IdentityMap.set(doc)
|
|
130
130
|
end
|
|
131
131
|
end
|
|
@@ -29,16 +29,40 @@ module Mongoid #:nodoc:
|
|
|
29
29
|
#
|
|
30
30
|
# @since 2.0.0.beta.1
|
|
31
31
|
def <<(*args)
|
|
32
|
+
docs = args.flatten
|
|
33
|
+
return concat(docs) if docs.size > 1
|
|
34
|
+
if doc = docs.first
|
|
35
|
+
append(doc)
|
|
36
|
+
doc.save if persistable? && !_assigning? && !doc.validated?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
alias :push :<<
|
|
40
|
+
|
|
41
|
+
# Appends an array of documents to the relation. Performs a batch
|
|
42
|
+
# insert of the documents instead of persisting one at a time.
|
|
43
|
+
#
|
|
44
|
+
# @note When performing batch inserts the *after* callbacks will get
|
|
45
|
+
# executed before the documents have actually been persisted to the
|
|
46
|
+
# database due to an issue with Active Support's callback system - we
|
|
47
|
+
# cannot explicitly fire the after callbacks by themselves.
|
|
48
|
+
#
|
|
49
|
+
# @example Concat with other documents.
|
|
50
|
+
# person.posts.concat([ post_one, post_two ])
|
|
51
|
+
#
|
|
52
|
+
# @param [ Array<Document> ] documents The docs to add.
|
|
53
|
+
#
|
|
54
|
+
# @return [ Array<Document> ] The documents.
|
|
55
|
+
#
|
|
56
|
+
# @since 2.4.0
|
|
57
|
+
def concat(documents)
|
|
32
58
|
batched do
|
|
33
|
-
|
|
59
|
+
documents.each do |doc|
|
|
34
60
|
next unless doc
|
|
35
61
|
append(doc)
|
|
36
|
-
doc.save if persistable?
|
|
62
|
+
doc.save if persistable?
|
|
37
63
|
end
|
|
38
64
|
end
|
|
39
65
|
end
|
|
40
|
-
alias :concat :<<
|
|
41
|
-
alias :push :<<
|
|
42
66
|
|
|
43
67
|
# Build a new document from the attributes and append it to this
|
|
44
68
|
# relation without saving.
|
|
@@ -66,6 +90,7 @@ module Mongoid #:nodoc:
|
|
|
66
90
|
Factory.build(type || klass, attributes, options).tap do |doc|
|
|
67
91
|
append(doc)
|
|
68
92
|
yield(doc) if block_given?
|
|
93
|
+
doc.run_callbacks(:build) { doc }
|
|
69
94
|
end
|
|
70
95
|
end
|
|
71
96
|
alias :new :build
|
|
@@ -293,13 +318,37 @@ module Mongoid #:nodoc:
|
|
|
293
318
|
# @since 2.0.0.rc.1
|
|
294
319
|
def substitute(replacement)
|
|
295
320
|
tap do |proxy|
|
|
296
|
-
if replacement
|
|
321
|
+
if replacement
|
|
322
|
+
if replacement != proxy.in_memory
|
|
323
|
+
new_docs, docs = replacement.compact.uniq, []
|
|
324
|
+
new_ids = new_docs.map { |doc| doc.id }
|
|
325
|
+
remove_not_in(new_ids)
|
|
326
|
+
new_docs.each do |doc|
|
|
327
|
+
docs.push(doc) if doc.send(metadata.foreign_key) != base.id
|
|
328
|
+
end
|
|
329
|
+
proxy.concat(docs)
|
|
330
|
+
end
|
|
331
|
+
else
|
|
297
332
|
proxy.purge
|
|
298
|
-
proxy.push(replacement.compact.uniq) if replacement
|
|
299
333
|
end
|
|
300
334
|
end
|
|
301
335
|
end
|
|
302
336
|
|
|
337
|
+
# Get a criteria for the documents without the default scoping
|
|
338
|
+
# applied.
|
|
339
|
+
#
|
|
340
|
+
# @example Get the unscoped criteria.
|
|
341
|
+
# person.posts.unscoped
|
|
342
|
+
#
|
|
343
|
+
# @return [ Criteria ] The unscoped criteria.
|
|
344
|
+
#
|
|
345
|
+
# @since 2.4.0
|
|
346
|
+
def unscoped
|
|
347
|
+
klass.unscoped.where(
|
|
348
|
+
metadata.foreign_key => Conversions.flag(base.id, metadata)
|
|
349
|
+
)
|
|
350
|
+
end
|
|
351
|
+
|
|
303
352
|
private
|
|
304
353
|
|
|
305
354
|
# Appends the document to the target array, updating the index on the
|
|
@@ -408,7 +457,7 @@ module Mongoid #:nodoc:
|
|
|
408
457
|
#
|
|
409
458
|
# @since 2.1.0
|
|
410
459
|
def persistable?
|
|
411
|
-
_creating? || base.persisted? && !
|
|
460
|
+
!_binding? && (_creating? || base.persisted? && !_building?)
|
|
412
461
|
end
|
|
413
462
|
|
|
414
463
|
# Deletes all related documents from the database given the supplied
|
|
@@ -437,6 +486,36 @@ module Mongoid #:nodoc:
|
|
|
437
486
|
end
|
|
438
487
|
end
|
|
439
488
|
|
|
489
|
+
# Remove all the documents in the proxy that do not have the provided
|
|
490
|
+
# ids.
|
|
491
|
+
#
|
|
492
|
+
# @todo: Durran: Refactor 3.0. Temp for bug fix in 2.4.
|
|
493
|
+
#
|
|
494
|
+
# @example Remove all documents without the ids.
|
|
495
|
+
# proxy.remove_not_in([ id ])
|
|
496
|
+
#
|
|
497
|
+
# @param [ Array<Object> ] ids The ids.
|
|
498
|
+
#
|
|
499
|
+
# @since 2.4.0
|
|
500
|
+
def remove_not_in(ids)
|
|
501
|
+
removed = criteria.not_in(:_id => ids)
|
|
502
|
+
if metadata.destructive?
|
|
503
|
+
removed.delete_all
|
|
504
|
+
else
|
|
505
|
+
removed.update(metadata.foreign_key => nil)
|
|
506
|
+
end
|
|
507
|
+
in_memory.each do |doc|
|
|
508
|
+
if !ids.include?(doc.id)
|
|
509
|
+
unbind_one(doc)
|
|
510
|
+
added.try { |p| p.delete_one(doc) }
|
|
511
|
+
loaded.try { |p| p.delete_one(doc) }
|
|
512
|
+
if metadata.destructive?
|
|
513
|
+
doc.destroyed = true
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
|
|
440
519
|
class << self
|
|
441
520
|
|
|
442
521
|
# Return the builder that is responsible for generating the documents
|
|
@@ -479,14 +558,14 @@ module Mongoid #:nodoc:
|
|
|
479
558
|
# Proxy.eager_load(metadata, criteria)
|
|
480
559
|
#
|
|
481
560
|
# @param [ Metadata ] metadata The relation metadata.
|
|
482
|
-
# @param [
|
|
561
|
+
# @param [ Array<Object> ] ids The ids of the base docs.
|
|
483
562
|
#
|
|
484
563
|
# @return [ Criteria ] The criteria to eager load the relation.
|
|
485
564
|
#
|
|
486
565
|
# @since 2.2.0
|
|
487
|
-
def eager_load(metadata,
|
|
566
|
+
def eager_load(metadata, ids)
|
|
488
567
|
klass, foreign_key = metadata.klass, metadata.foreign_key
|
|
489
|
-
klass.any_in(foreign_key =>
|
|
568
|
+
klass.any_in(foreign_key => ids).each do |doc|
|
|
490
569
|
IdentityMap.set_many(doc, foreign_key => doc.send(foreign_key))
|
|
491
570
|
end
|
|
492
571
|
end
|
|
@@ -81,49 +81,6 @@ module Mongoid # :nodoc:
|
|
|
81
81
|
end
|
|
82
82
|
alias :new :build
|
|
83
83
|
|
|
84
|
-
# Creates a new document on the references many relation. This will
|
|
85
|
-
# save the document if the parent has been persisted.
|
|
86
|
-
#
|
|
87
|
-
# @example Create and save the new document.
|
|
88
|
-
# person.posts.create(:text => "Testing")
|
|
89
|
-
#
|
|
90
|
-
# @param [ Hash ] attributes The attributes to create with.
|
|
91
|
-
# @param [ Class ] type The optional type of document to create.
|
|
92
|
-
#
|
|
93
|
-
# @return [ Document ] The newly created document.
|
|
94
|
-
#
|
|
95
|
-
# @since 2.0.0.beta.1
|
|
96
|
-
def create(attributes = nil, type = nil, &block)
|
|
97
|
-
super.tap do |doc|
|
|
98
|
-
base.send(metadata.foreign_key).delete_one(doc.id)
|
|
99
|
-
base.push(metadata.foreign_key, doc.id)
|
|
100
|
-
base.synced[metadata.foreign_key] = false
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Creates a new document on the references many relation. This will
|
|
105
|
-
# save the document if the parent has been persisted and will raise an
|
|
106
|
-
# error if validation fails.
|
|
107
|
-
#
|
|
108
|
-
# @example Create and save the new document.
|
|
109
|
-
# person.posts.create!(:text => "Testing")
|
|
110
|
-
#
|
|
111
|
-
# @param [ Hash ] attributes The attributes to create with.
|
|
112
|
-
# @param [ Class ] type The optional type of document to create.
|
|
113
|
-
#
|
|
114
|
-
# @raise [ Errors::Validations ] If validation failed.
|
|
115
|
-
#
|
|
116
|
-
# @return [ Document ] The newly created document.
|
|
117
|
-
#
|
|
118
|
-
# @since 2.0.0.beta.1
|
|
119
|
-
def create!(attributes = nil, type = nil, &block)
|
|
120
|
-
super.tap do |doc|
|
|
121
|
-
base.send(metadata.foreign_key).delete_one(doc.id)
|
|
122
|
-
base.push(metadata.foreign_key, doc.id)
|
|
123
|
-
base.synced[metadata.foreign_key] = false
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
84
|
# Delete the document from the relation. This will set the foreign key
|
|
128
85
|
# on the document to nil. If the dependent options on the relation are
|
|
129
86
|
# :delete or :destroy the appropriate removal will occur.
|
|
@@ -171,6 +128,40 @@ module Mongoid # :nodoc:
|
|
|
171
128
|
alias :clear :nullify
|
|
172
129
|
alias :purge :nullify
|
|
173
130
|
|
|
131
|
+
# Substitutes the supplied target documents for the existing documents
|
|
132
|
+
# in the relation. If the new target is nil, perform the necessary
|
|
133
|
+
# deletion.
|
|
134
|
+
#
|
|
135
|
+
# @example Replace the relation.
|
|
136
|
+
# person.preferences.substitute([ new_post ])
|
|
137
|
+
#
|
|
138
|
+
# @param [ Array<Document> ] replacement The replacement target.
|
|
139
|
+
#
|
|
140
|
+
# @return [ Many ] The relation.
|
|
141
|
+
#
|
|
142
|
+
# @since 2.0.0.rc.1
|
|
143
|
+
def substitute(replacement)
|
|
144
|
+
tap do |proxy|
|
|
145
|
+
if replacement != proxy.in_memory
|
|
146
|
+
proxy.purge
|
|
147
|
+
proxy.push(replacement.compact.uniq) if replacement
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Get a criteria for the documents without the default scoping
|
|
153
|
+
# applied.
|
|
154
|
+
#
|
|
155
|
+
# @example Get the unscoped criteria.
|
|
156
|
+
# person.preferences.unscoped
|
|
157
|
+
#
|
|
158
|
+
# @return [ Criteria ] The unscoped criteria.
|
|
159
|
+
#
|
|
160
|
+
# @since 2.4.0
|
|
161
|
+
def unscoped
|
|
162
|
+
klass.unscoped.any_in(:_id => base.send(metadata.foreign_key))
|
|
163
|
+
end
|
|
164
|
+
|
|
174
165
|
private
|
|
175
166
|
|
|
176
167
|
# Appends the document to the target array, updating the index on the
|
|
@@ -53,7 +53,11 @@ module Mongoid # :nodoc:
|
|
|
53
53
|
def substitute(replacement)
|
|
54
54
|
unbind_one
|
|
55
55
|
if persistable?
|
|
56
|
-
metadata.destructive?
|
|
56
|
+
if metadata.destructive?
|
|
57
|
+
send(metadata.dependent)
|
|
58
|
+
else
|
|
59
|
+
save if persisted?
|
|
60
|
+
end
|
|
57
61
|
end
|
|
58
62
|
return nil unless replacement
|
|
59
63
|
One.new(base, replacement, metadata)
|
|
@@ -128,14 +132,14 @@ module Mongoid # :nodoc:
|
|
|
128
132
|
# Proxy.eager_load(metadata, criteria)
|
|
129
133
|
#
|
|
130
134
|
# @param [ Metadata ] metadata The relation metadata.
|
|
131
|
-
# @param [
|
|
135
|
+
# @param [ Array<Object> ] ids The ids of the base docs.
|
|
132
136
|
#
|
|
133
137
|
# @return [ Criteria ] The criteria to eager load the relation.
|
|
134
138
|
#
|
|
135
139
|
# @since 2.2.0
|
|
136
|
-
def eager_load(metadata,
|
|
140
|
+
def eager_load(metadata, ids)
|
|
137
141
|
klass, foreign_key = metadata.klass, metadata.foreign_key
|
|
138
|
-
klass.any_in(foreign_key =>
|
|
142
|
+
klass.any_in(foreign_key => ids).each do |doc|
|
|
139
143
|
IdentityMap.set_one(doc, foreign_key => doc.send(foreign_key))
|
|
140
144
|
end
|
|
141
145
|
end
|
|
@@ -75,11 +75,28 @@ module Mongoid # :nodoc:
|
|
|
75
75
|
#
|
|
76
76
|
# @since 2.1.0
|
|
77
77
|
def update_inverse_keys(meta)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
if changes.has_key?(meta.foreign_key)
|
|
79
|
+
old, new = changes[meta.foreign_key]
|
|
80
|
+
adds, subs = new - (old || []), (old || []) - new
|
|
81
|
+
|
|
82
|
+
# If we are autosaving we don't want a duplicate to get added - the
|
|
83
|
+
# $addToSet would run previously and then the $pushAll from the
|
|
84
|
+
# inverse on the autosave would cause this. We delete each id from
|
|
85
|
+
# what's in memory in case a mix of id addition and object addition
|
|
86
|
+
# had occurred.
|
|
87
|
+
if meta.autosave?
|
|
88
|
+
send(meta.name).in_memory.each do |doc|
|
|
89
|
+
adds.delete_one(doc.id)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
unless adds.empty?
|
|
94
|
+
meta.criteria(adds).add_to_set(meta.inverse_foreign_key, id)
|
|
95
|
+
end
|
|
96
|
+
unless subs.empty?
|
|
97
|
+
meta.criteria(subs).pull(meta.inverse_foreign_key, id)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
83
100
|
end
|
|
84
101
|
|
|
85
102
|
module ClassMethods #:nodoc:
|
data/lib/mongoid/threaded.rb
CHANGED
|
@@ -8,76 +8,60 @@ module Mongoid #:nodoc:
|
|
|
8
8
|
module Threaded
|
|
9
9
|
extend self
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# Begin entry into a named thread local stack.
|
|
12
12
|
#
|
|
13
|
-
# @example Begin the
|
|
14
|
-
# Threaded.
|
|
13
|
+
# @example Begin entry into the stack.
|
|
14
|
+
# Threaded.begin(:create)
|
|
15
15
|
#
|
|
16
|
-
# @
|
|
16
|
+
# @param [ Symbol ] name The name of the stack
|
|
17
17
|
#
|
|
18
|
-
# @
|
|
19
|
-
def begin_assign
|
|
20
|
-
assign_stack.push(true)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Begins a binding block.
|
|
24
|
-
#
|
|
25
|
-
# @example Begin the bind.
|
|
26
|
-
# Threaded.begin_bind
|
|
18
|
+
# @return [ true ] True.
|
|
27
19
|
#
|
|
28
|
-
# @
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def begin_bind
|
|
32
|
-
bind_stack.push(true)
|
|
20
|
+
# @since 2.4.0
|
|
21
|
+
def begin(name)
|
|
22
|
+
stack(name).push(true)
|
|
33
23
|
end
|
|
34
24
|
|
|
35
|
-
#
|
|
25
|
+
# Are in the middle of executing the named stack
|
|
36
26
|
#
|
|
37
|
-
# @example
|
|
38
|
-
# Threaded.
|
|
27
|
+
# @example Are we in the stack execution?
|
|
28
|
+
# Threaded.executing?(:create)
|
|
39
29
|
#
|
|
40
|
-
# @
|
|
30
|
+
# @param [ Symbol ] name The name of the stack
|
|
41
31
|
#
|
|
42
|
-
# @
|
|
43
|
-
def begin_build
|
|
44
|
-
build_stack.push(true)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Begins a creating block.
|
|
48
|
-
#
|
|
49
|
-
# @example Begin the create.
|
|
50
|
-
# Threaded.begin_create
|
|
32
|
+
# @return [ true ] If the stack is being executed.
|
|
51
33
|
#
|
|
52
|
-
# @
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def begin_create
|
|
56
|
-
create_stack.push(true)
|
|
34
|
+
# @since 2.4.0
|
|
35
|
+
def executing?(name)
|
|
36
|
+
!stack(name).empty?
|
|
57
37
|
end
|
|
58
38
|
|
|
59
|
-
#
|
|
39
|
+
# Exit from a named thread local stack.
|
|
60
40
|
#
|
|
61
|
-
# @example
|
|
62
|
-
# Threaded.
|
|
41
|
+
# @example Exit from the stack.
|
|
42
|
+
# Threaded.exit(:create)
|
|
63
43
|
#
|
|
64
|
-
# @
|
|
44
|
+
# @param [ Symbol ] name The name of the stack
|
|
65
45
|
#
|
|
66
|
-
# @
|
|
67
|
-
|
|
68
|
-
|
|
46
|
+
# @return [ true ] True.
|
|
47
|
+
#
|
|
48
|
+
# @since 2.4.0
|
|
49
|
+
def exit(name)
|
|
50
|
+
stack(name).pop
|
|
69
51
|
end
|
|
70
52
|
|
|
71
|
-
#
|
|
53
|
+
# Get the named stack.
|
|
54
|
+
#
|
|
55
|
+
# @example Get a stack by name
|
|
56
|
+
# Threaded.stack(:create)
|
|
72
57
|
#
|
|
73
|
-
# @
|
|
74
|
-
# Threaded.begin_load_revision
|
|
58
|
+
# @param [ Symbol ] name The name of the stack
|
|
75
59
|
#
|
|
76
|
-
# @return [
|
|
60
|
+
# @return [ Array ] The stack.
|
|
77
61
|
#
|
|
78
|
-
# @since 2.
|
|
79
|
-
def
|
|
80
|
-
|
|
62
|
+
# @since 2.4.0
|
|
63
|
+
def stack(name)
|
|
64
|
+
Thread.current[:"[mongoid]:#{name}-stack"] ||= []
|
|
81
65
|
end
|
|
82
66
|
|
|
83
67
|
# Begin validating a document on the current thread.
|
|
@@ -92,156 +76,6 @@ module Mongoid #:nodoc:
|
|
|
92
76
|
validations_for(document.class).push(document.id)
|
|
93
77
|
end
|
|
94
78
|
|
|
95
|
-
# Is the current thread in assigning mode?
|
|
96
|
-
#
|
|
97
|
-
# @example Is the thread in assigning mode?
|
|
98
|
-
# Threaded.assigning?
|
|
99
|
-
#
|
|
100
|
-
# @return [ true, false ] If the thread is in assigning mode?
|
|
101
|
-
#
|
|
102
|
-
# @since 2.1.0
|
|
103
|
-
def assigning?
|
|
104
|
-
!assign_stack.empty?
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Is the current thread in binding mode?
|
|
108
|
-
#
|
|
109
|
-
# @example Is the thread in binding mode?
|
|
110
|
-
# Threaded.binding?
|
|
111
|
-
#
|
|
112
|
-
# @return [ true, false ] If the thread is in binding mode?
|
|
113
|
-
#
|
|
114
|
-
# @since 2.1.0
|
|
115
|
-
def binding?
|
|
116
|
-
!bind_stack.empty?
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Is the current thread in building mode?
|
|
120
|
-
#
|
|
121
|
-
# @example Is the thread in building mode?
|
|
122
|
-
# Threaded.building?
|
|
123
|
-
#
|
|
124
|
-
# @return [ true, false ] If the thread is in building mode?
|
|
125
|
-
#
|
|
126
|
-
# @since 2.1.0
|
|
127
|
-
def building?
|
|
128
|
-
!build_stack.empty?
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
# Is the current thread in creating mode?
|
|
132
|
-
#
|
|
133
|
-
# @example Is the thread in creating mode?
|
|
134
|
-
# Threaded.creating?
|
|
135
|
-
#
|
|
136
|
-
# @return [ true, false ] If the thread is in creating mode?
|
|
137
|
-
#
|
|
138
|
-
# @since 2.1.0
|
|
139
|
-
def creating?
|
|
140
|
-
!create_stack.empty?
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# Is the current thread in loading mode?
|
|
144
|
-
#
|
|
145
|
-
# @example Is the thread in loading mode?
|
|
146
|
-
# Threaded.loading?
|
|
147
|
-
#
|
|
148
|
-
# @return [ true, false ] If the thread is in loading mode?
|
|
149
|
-
#
|
|
150
|
-
# @since 2.3.2
|
|
151
|
-
def loading?
|
|
152
|
-
!load_stack.empty?
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Is the current thread in revision load mode?
|
|
156
|
-
#
|
|
157
|
-
# @example Is the thread in revision load mode?
|
|
158
|
-
# Threaded.loading_revision?
|
|
159
|
-
#
|
|
160
|
-
# @return [ true, false ] If the thread is in revision load mode?
|
|
161
|
-
#
|
|
162
|
-
# @since 2.3.4
|
|
163
|
-
def loading_revision?
|
|
164
|
-
!load_revision_stack.empty?
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
# Get the assign stack for the current thread. Is simply an array of calls
|
|
168
|
-
# to Mongoid's assigning method.
|
|
169
|
-
#
|
|
170
|
-
# @example Get the assign stack.
|
|
171
|
-
# Threaded.assign_stack
|
|
172
|
-
#
|
|
173
|
-
# @return [ Array ] The array of assign calls.
|
|
174
|
-
#
|
|
175
|
-
# @since 2.1.9
|
|
176
|
-
def assign_stack
|
|
177
|
-
Thread.current[:"[mongoid]:assign-stack"] ||= []
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Get the bind stack for the current thread. Is simply an array of calls
|
|
181
|
-
# to Mongoid's binding method.
|
|
182
|
-
#
|
|
183
|
-
# @example Get the bind stack.
|
|
184
|
-
# Threaded.bind_stack
|
|
185
|
-
#
|
|
186
|
-
# @return [ Array ] The array of bind calls.
|
|
187
|
-
#
|
|
188
|
-
# @since 2.1.9
|
|
189
|
-
def bind_stack
|
|
190
|
-
Thread.current[:"[mongoid]:bind-stack"] ||= []
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# Get the build stack for the current thread. Is simply an array of calls
|
|
194
|
-
# to Mongoid's building method.
|
|
195
|
-
#
|
|
196
|
-
# @example Get the build stack.
|
|
197
|
-
# Threaded.build_stack
|
|
198
|
-
#
|
|
199
|
-
# @return [ Array ] The array of build calls.
|
|
200
|
-
#
|
|
201
|
-
# @since 2.1.9
|
|
202
|
-
def build_stack
|
|
203
|
-
Thread.current[:"[mongoid]:build-stack"] ||= []
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
# Get the create stack for the current thread. Is simply an array of calls
|
|
207
|
-
# to Mongoid's creating method.
|
|
208
|
-
#
|
|
209
|
-
# @example Get the create stack.
|
|
210
|
-
# Threaded.create_stack
|
|
211
|
-
#
|
|
212
|
-
# @return [ Array ] The array of create calls.
|
|
213
|
-
#
|
|
214
|
-
# @since 2.1.9
|
|
215
|
-
def create_stack
|
|
216
|
-
Thread.current[:"[mongoid]:create-stack"] ||= []
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
# Get the load stack for the current thread. Is simply an array of calls
|
|
220
|
-
# to Mongoid's loading method.
|
|
221
|
-
#
|
|
222
|
-
# @example Get the load stack.
|
|
223
|
-
# Threaded.load_stack
|
|
224
|
-
#
|
|
225
|
-
# @return [ Array ] The array of load calls.
|
|
226
|
-
#
|
|
227
|
-
# @since 2.3.2
|
|
228
|
-
def load_stack
|
|
229
|
-
Thread.current[:"[mongoid]:load-stack"] ||= []
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
# Get the revision load stack for the current thread. Is simply an array
|
|
233
|
-
# of calls to Mongoid's loading_revision method.
|
|
234
|
-
#
|
|
235
|
-
# @example Get the revision load stack.
|
|
236
|
-
# Threaded.load_revision_stack
|
|
237
|
-
#
|
|
238
|
-
# @return [ Array ] The array of load revision calls.
|
|
239
|
-
#
|
|
240
|
-
# @since 2.3.4
|
|
241
|
-
def load_revision_stack
|
|
242
|
-
Thread.current[:"[mongoid]:load-revision-stack"] ||= []
|
|
243
|
-
end
|
|
244
|
-
|
|
245
79
|
# Clear out all the safety options set using the safely proxy.
|
|
246
80
|
#
|
|
247
81
|
# @example Clear out the options.
|
|
@@ -265,78 +99,6 @@ module Mongoid #:nodoc:
|
|
|
265
99
|
self.timeless = false
|
|
266
100
|
end
|
|
267
101
|
|
|
268
|
-
# Exit the assigning block.
|
|
269
|
-
#
|
|
270
|
-
# @example Exit the assigning block.
|
|
271
|
-
# Threaded.exit_assign
|
|
272
|
-
#
|
|
273
|
-
# @return [ true ] The last element in the stack.
|
|
274
|
-
#
|
|
275
|
-
# @since 2.1.9
|
|
276
|
-
def exit_assign
|
|
277
|
-
assign_stack.pop
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# Exit the binding block.
|
|
281
|
-
#
|
|
282
|
-
# @example Exit the binding block.
|
|
283
|
-
# Threaded.exit_bind
|
|
284
|
-
#
|
|
285
|
-
# @return [ true ] The last element in the stack.
|
|
286
|
-
#
|
|
287
|
-
# @since 2.1.9
|
|
288
|
-
def exit_bind
|
|
289
|
-
bind_stack.pop
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
# Exit the building block.
|
|
293
|
-
#
|
|
294
|
-
# @example Exit the building block.
|
|
295
|
-
# Threaded.exit_build
|
|
296
|
-
#
|
|
297
|
-
# @return [ true ] The last element in the stack.
|
|
298
|
-
#
|
|
299
|
-
# @since 2.1.9
|
|
300
|
-
def exit_build
|
|
301
|
-
build_stack.pop
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
# Exit the creating block.
|
|
305
|
-
#
|
|
306
|
-
# @example Exit the creating block.
|
|
307
|
-
# Threaded.exit_create
|
|
308
|
-
#
|
|
309
|
-
# @return [ true ] The last element in the stack.
|
|
310
|
-
#
|
|
311
|
-
# @since 2.1.9
|
|
312
|
-
def exit_create
|
|
313
|
-
create_stack.pop
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
# Exit the loading block.
|
|
317
|
-
#
|
|
318
|
-
# @example Exit the loading block.
|
|
319
|
-
# Threaded.exit_load
|
|
320
|
-
#
|
|
321
|
-
# @return [ true ] The last element in the stack.
|
|
322
|
-
#
|
|
323
|
-
# @since 2.1.9
|
|
324
|
-
def exit_load
|
|
325
|
-
load_stack.pop
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
# Exit the revision loading block.
|
|
329
|
-
#
|
|
330
|
-
# @example Exit the revision loading block.
|
|
331
|
-
# Threaded.exit_load_revision
|
|
332
|
-
#
|
|
333
|
-
# @return [ true ] The last element in the stack.
|
|
334
|
-
#
|
|
335
|
-
# @since 2.3.4
|
|
336
|
-
def exit_load_revision
|
|
337
|
-
load_revision_stack.pop
|
|
338
|
-
end
|
|
339
|
-
|
|
340
102
|
# Exit validating a document on the current thread.
|
|
341
103
|
#
|
|
342
104
|
# @example Exit validation.
|
|
@@ -369,8 +131,8 @@ module Mongoid #:nodoc:
|
|
|
369
131
|
# @return [ Object ] The batch insert consumer.
|
|
370
132
|
#
|
|
371
133
|
# @since 2.1.0
|
|
372
|
-
def insert
|
|
373
|
-
Thread.current[:"[mongoid]:insert-consumer"]
|
|
134
|
+
def insert(name)
|
|
135
|
+
Thread.current[:"[mongoid][#{name}]:insert-consumer"]
|
|
374
136
|
end
|
|
375
137
|
|
|
376
138
|
# Set the insert consumer on the current thread.
|
|
@@ -383,8 +145,8 @@ module Mongoid #:nodoc:
|
|
|
383
145
|
# @return [ Object ] The insert consumer.
|
|
384
146
|
#
|
|
385
147
|
# @since 2.1.0
|
|
386
|
-
def
|
|
387
|
-
Thread.current[:"[mongoid]:insert-consumer"] = consumer
|
|
148
|
+
def set_insert(name, consumer)
|
|
149
|
+
Thread.current[:"[mongoid][#{name}]:insert-consumer"] = consumer
|
|
388
150
|
end
|
|
389
151
|
|
|
390
152
|
# Get the safety options for the current thread.
|