mongoid 2.0.1 → 2.0.2
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/Rakefile +4 -4
- data/lib/config/locales/{pt-br.yml → pt-BR.yml} +5 -5
- data/lib/config/locales/ru.yml +1 -1
- data/lib/config/locales/zh-CN.yml +2 -0
- data/lib/mongoid.rb +0 -1
- data/lib/mongoid/attributes.rb +9 -6
- data/lib/mongoid/collection.rb +21 -0
- data/lib/mongoid/config.rb +31 -8
- data/lib/mongoid/config/replset_database.rb +32 -2
- data/lib/mongoid/contexts.rb +0 -1
- data/lib/mongoid/contexts/enumerable.rb +73 -36
- data/lib/mongoid/contexts/mongo.rb +5 -12
- data/lib/mongoid/copyable.rb +2 -2
- data/lib/mongoid/criteria.rb +4 -23
- data/lib/mongoid/criterion/exclusion.rb +15 -0
- data/lib/mongoid/criterion/inclusion.rb +1 -1
- data/lib/mongoid/criterion/optional.rb +0 -1
- data/lib/mongoid/criterion/unconvertable.rb +20 -0
- data/lib/mongoid/cursor.rb +3 -3
- data/lib/mongoid/dirty.rb +8 -8
- data/lib/mongoid/document.rb +33 -36
- data/lib/mongoid/extensions.rb +7 -0
- data/lib/mongoid/extensions/object/checks.rb +32 -0
- data/lib/mongoid/extensions/object/conversions.rb +1 -1
- data/lib/mongoid/extensions/object_id/conversions.rb +6 -1
- data/lib/mongoid/extensions/range/conversions.rb +25 -0
- data/lib/mongoid/factory.rb +27 -10
- data/lib/mongoid/field.rb +50 -0
- data/lib/mongoid/fields.rb +42 -7
- data/lib/mongoid/finders.rb +5 -17
- data/lib/mongoid/identity.rb +1 -1
- data/lib/mongoid/inspection.rb +17 -21
- data/lib/mongoid/matchers.rb +6 -2
- data/lib/mongoid/matchers/strategies.rb +2 -2
- data/lib/mongoid/named_scope.rb +1 -1
- data/lib/mongoid/observer.rb +45 -14
- data/lib/mongoid/paranoia.rb +2 -2
- data/lib/mongoid/persistence.rb +2 -2
- data/lib/mongoid/persistence/update.rb +2 -1
- data/lib/mongoid/railtie.rb +3 -5
- data/lib/mongoid/relations.rb +1 -0
- data/lib/mongoid/relations/builders.rb +3 -3
- data/lib/mongoid/relations/builders/embedded/in.rb +1 -1
- data/lib/mongoid/relations/builders/embedded/many.rb +1 -1
- data/lib/mongoid/relations/builders/embedded/one.rb +1 -2
- data/lib/mongoid/relations/builders/referenced/in.rb +0 -3
- data/lib/mongoid/relations/builders/referenced/many.rb +21 -1
- data/lib/mongoid/relations/builders/referenced/one.rb +0 -4
- data/lib/mongoid/relations/embedded/many.rb +1 -17
- data/lib/mongoid/relations/macros.rb +3 -2
- data/lib/mongoid/relations/many.rb +2 -0
- data/lib/mongoid/relations/proxy.rb +1 -1
- data/lib/mongoid/relations/referenced/batch.rb +71 -0
- data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
- data/lib/mongoid/relations/referenced/many.rb +61 -2
- data/lib/mongoid/serialization.rb +1 -1
- data/lib/mongoid/validations/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +8 -11
- metadata +22 -64
- data/lib/mongoid/contexts/paging.rb +0 -50
data/lib/mongoid/paranoia.rb
CHANGED
@@ -49,7 +49,7 @@ module Mongoid #:nodoc:
|
|
49
49
|
# true
|
50
50
|
def remove(options = {})
|
51
51
|
now = Time.now
|
52
|
-
collection.update({ :_id =>
|
52
|
+
collection.update({ :_id => id }, { '$set' => { :deleted_at => now } })
|
53
53
|
@attributes["deleted_at"] = now
|
54
54
|
true
|
55
55
|
end
|
@@ -72,7 +72,7 @@ module Mongoid #:nodoc:
|
|
72
72
|
#
|
73
73
|
# <tt>document.restore</tt>
|
74
74
|
def restore
|
75
|
-
collection.update({ :_id =>
|
75
|
+
collection.update({ :_id => id }, { '$unset' => { :deleted_at => true } })
|
76
76
|
@attributes.delete("deleted_at")
|
77
77
|
end
|
78
78
|
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -57,7 +57,7 @@ module Mongoid #:nodoc:
|
|
57
57
|
# @return [ TrueClass ] True.
|
58
58
|
def remove(options = {})
|
59
59
|
if Remove.new(self, options).persist
|
60
|
-
|
60
|
+
attributes.freeze
|
61
61
|
self.destroyed = true
|
62
62
|
cascade!
|
63
63
|
end; true
|
@@ -102,7 +102,7 @@ module Mongoid #:nodoc:
|
|
102
102
|
#
|
103
103
|
# @since 2.0.0.rc.6
|
104
104
|
def update_attribute(name, value)
|
105
|
-
write_attribute(name, value)
|
105
|
+
write_attribute(name, value) ? save(:validate => false) : true
|
106
106
|
end
|
107
107
|
|
108
108
|
# Update the document attributes in the datbase.
|
data/lib/mongoid/railtie.rb
CHANGED
@@ -45,8 +45,9 @@ module Rails #:nodoc:
|
|
45
45
|
#
|
46
46
|
# @example mongoid.yml
|
47
47
|
#
|
48
|
-
#
|
48
|
+
# development:
|
49
49
|
# host: localhost
|
50
|
+
# database: mongoid
|
50
51
|
# slaves:
|
51
52
|
# # - host: localhost
|
52
53
|
# # port: 27018
|
@@ -56,9 +57,6 @@ module Rails #:nodoc:
|
|
56
57
|
# parameterize_keys: false
|
57
58
|
# persist_in_safe_mode: false
|
58
59
|
#
|
59
|
-
# development:
|
60
|
-
# <<: *defaults
|
61
|
-
# database: mongoid
|
62
60
|
initializer "setup database" do
|
63
61
|
config_file = Rails.root.join("config", "mongoid.yml")
|
64
62
|
if config_file.file?
|
@@ -131,7 +129,7 @@ module Rails #:nodoc:
|
|
131
129
|
config.after_initialize do
|
132
130
|
::Mongoid.instantiate_observers
|
133
131
|
|
134
|
-
ActionDispatch::Callbacks.to_prepare
|
132
|
+
ActionDispatch::Callbacks.to_prepare do
|
135
133
|
::Mongoid.instantiate_observers
|
136
134
|
end
|
137
135
|
end
|
data/lib/mongoid/relations.rb
CHANGED
@@ -14,6 +14,7 @@ require "mongoid/relations/embedded/atomic"
|
|
14
14
|
require "mongoid/relations/embedded/in"
|
15
15
|
require "mongoid/relations/embedded/many"
|
16
16
|
require "mongoid/relations/embedded/one"
|
17
|
+
require "mongoid/relations/referenced/batch"
|
17
18
|
require "mongoid/relations/referenced/in"
|
18
19
|
require "mongoid/relations/referenced/many"
|
19
20
|
require "mongoid/relations/referenced/many_to_many"
|
@@ -45,11 +45,11 @@ module Mongoid # :nodoc:
|
|
45
45
|
# @return [ Class ] The class being set up.
|
46
46
|
#
|
47
47
|
# @since 2.0.0.rc.1
|
48
|
-
def builder(name)
|
48
|
+
def builder(name, metadata)
|
49
49
|
tap do
|
50
50
|
define_method("build_#{name}") do |*args|
|
51
|
-
|
52
|
-
send("#{name}=",
|
51
|
+
document = Factory.build(metadata.klass, args.first || {})
|
52
|
+
send("#{name}=", document, :binding => true)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -16,7 +16,7 @@ module Mongoid # :nodoc:
|
|
16
16
|
# @return [ Document ] A single document.
|
17
17
|
def build(type = nil)
|
18
18
|
return object unless object.is_a?(Hash)
|
19
|
-
Mongoid::Factory.
|
19
|
+
Mongoid::Factory.from_db(metadata.klass, object)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -21,7 +21,7 @@ module Mongoid # :nodoc:
|
|
21
21
|
return object if object.first.is_a?(Document)
|
22
22
|
object.inject([]) do |documents, attrs|
|
23
23
|
documents.tap do |docs|
|
24
|
-
docs << Mongoid::Factory.
|
24
|
+
docs << Mongoid::Factory.from_db(metadata.klass, attrs)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -17,8 +17,7 @@ module Mongoid # :nodoc:
|
|
17
17
|
# @return [ Document ] A single document.
|
18
18
|
def build(type = nil)
|
19
19
|
return object unless object.is_a?(Hash)
|
20
|
-
|
21
|
-
Mongoid::Factory.build(metadata.klass, object)
|
20
|
+
Mongoid::Factory.from_db(metadata.klass, object)
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
@@ -16,9 +16,6 @@ module Mongoid # :nodoc:
|
|
16
16
|
# @return [ Document ] A single document.
|
17
17
|
def build(type = nil)
|
18
18
|
return object unless query?
|
19
|
-
if object.is_a?(Hash)
|
20
|
-
return Mongoid::Factory.build(metadata.klass, object)
|
21
|
-
end
|
22
19
|
begin
|
23
20
|
(type ? type.constantize : metadata.klass).find(object)
|
24
21
|
rescue Errors::DocumentNotFound
|
@@ -18,7 +18,27 @@ module Mongoid # :nodoc:
|
|
18
18
|
return object unless query?
|
19
19
|
return [] if object.is_a?(Array)
|
20
20
|
key = metadata.foreign_key
|
21
|
-
metadata.klass.
|
21
|
+
metadata.klass.where(key => convertable(metadata, object))
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Get the value for the foreign key in convertable or unconvertable
|
27
|
+
# form.
|
28
|
+
#
|
29
|
+
# @example Get the value.
|
30
|
+
# builder.convertable
|
31
|
+
#
|
32
|
+
# @return [ String, Unconvertable, BSON::ObjectId ] The string or object id.
|
33
|
+
#
|
34
|
+
# @since 2.0.2
|
35
|
+
def convertable(metadata, object)
|
36
|
+
inverse = metadata.inverse_klass
|
37
|
+
if inverse.using_object_ids? || object.is_a?(BSON::ObjectId)
|
38
|
+
object
|
39
|
+
else
|
40
|
+
Mongoid::Criterion::Unconvertable.new(object)
|
41
|
+
end
|
22
42
|
end
|
23
43
|
end
|
24
44
|
end
|
@@ -16,10 +16,6 @@ module Mongoid # :nodoc:
|
|
16
16
|
# @return [ Document ] A single document.
|
17
17
|
def build(type = nil)
|
18
18
|
return object unless query?
|
19
|
-
if object.is_a?(Hash)
|
20
|
-
object.delete(:binding)
|
21
|
-
return Mongoid::Factory.build(metadata.klass, object)
|
22
|
-
end
|
23
19
|
metadata.klass.first(
|
24
20
|
:conditions => { metadata.foreign_key => object }
|
25
21
|
)
|
@@ -232,22 +232,6 @@ module Mongoid # :nodoc:
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
-
# Paginate the association. Will create a new criteria, set the documents
|
236
|
-
# on it and execute in an enumerable context.
|
237
|
-
#
|
238
|
-
# @example Paginate the relation.
|
239
|
-
# person.addresses.paginate(:page => 1, :per_page => 20)
|
240
|
-
#
|
241
|
-
# @param [ Hash ] options The pagination options.
|
242
|
-
#
|
243
|
-
# @option options [ Integer ] :page The page number.
|
244
|
-
# @option options [ Integer ] :per_page The number on each page.
|
245
|
-
#
|
246
|
-
# @return [ WillPaginate::Collection ] The paginated documents.
|
247
|
-
def paginate(options)
|
248
|
-
criteria.paginate(options)
|
249
|
-
end
|
250
|
-
|
251
235
|
# Substitutes the supplied target documents for the existing documents
|
252
236
|
# in the relation.
|
253
237
|
#
|
@@ -370,7 +354,7 @@ module Mongoid # :nodoc:
|
|
370
354
|
load!(:binding => true) and return super if target.respond_to?(name)
|
371
355
|
klass = metadata.klass
|
372
356
|
klass.send(:with_scope, criteria) do
|
373
|
-
criteria.send(name, *args)
|
357
|
+
criteria.send(name, *args, &block)
|
374
358
|
end
|
375
359
|
end
|
376
360
|
|
@@ -104,7 +104,7 @@ module Mongoid # :nodoc:
|
|
104
104
|
def embeds_one(name, options = {}, &block)
|
105
105
|
characterize(name, Embedded::One, options, &block).tap do |meta|
|
106
106
|
relate(name, meta)
|
107
|
-
builder(name).creator(name)
|
107
|
+
builder(name, meta).creator(name)
|
108
108
|
validates_relation(meta)
|
109
109
|
end
|
110
110
|
end
|
@@ -131,6 +131,7 @@ module Mongoid # :nodoc:
|
|
131
131
|
characterize(name, Referenced::In, options, &block).tap do |meta|
|
132
132
|
relate(name, meta)
|
133
133
|
reference(meta)
|
134
|
+
autosave(meta)
|
134
135
|
validates_relation(meta)
|
135
136
|
end
|
136
137
|
end
|
@@ -218,7 +219,7 @@ module Mongoid # :nodoc:
|
|
218
219
|
characterize(name, Referenced::One, options, &block).tap do |meta|
|
219
220
|
relate(name, meta)
|
220
221
|
reference(meta)
|
221
|
-
builder(name).creator(name).autosave(meta)
|
222
|
+
builder(name, meta).creator(name).autosave(meta)
|
222
223
|
validates_relation(meta)
|
223
224
|
end
|
224
225
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "mongoid/relations/referenced/batch/insert"
|
3
|
+
|
4
|
+
module Mongoid #:nodoc:
|
5
|
+
module Relations #:nodoc:
|
6
|
+
module Referenced #:nodoc:
|
7
|
+
|
8
|
+
# This module provides the ability for single insert calls to be batch
|
9
|
+
# inserted.
|
10
|
+
module Batch
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Executes a number of save calls in a single batch. Mongoid will
|
15
|
+
# intercept all database inserts while in this block and combine them
|
16
|
+
# into a single database call. When the block concludes the batch
|
17
|
+
# insert will occur.
|
18
|
+
#
|
19
|
+
# Since the collection is accessed through the class it would not be
|
20
|
+
# thread safe to give it state so we access the atomic updater via the
|
21
|
+
# current thread.
|
22
|
+
#
|
23
|
+
# @note This operation is not safe when attemping to do illegal updates
|
24
|
+
# for different objects or collections, since the updator is not
|
25
|
+
# scoped on the thread. This is meant for Mongoid internal use only
|
26
|
+
# to keep existing design clean.
|
27
|
+
#
|
28
|
+
# @example Batch update multiple appends.
|
29
|
+
# batched do
|
30
|
+
# person.posts << [ post_one, post_two, post_three ]
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @param [ Proc ] block The block to execute.
|
34
|
+
#
|
35
|
+
# @return [ Object ] The result of the operation.
|
36
|
+
#
|
37
|
+
# @since 2.0.2, batch-relational-insert
|
38
|
+
def batched(&block)
|
39
|
+
inserter = Thread.current[:mongoid_batch_insert] ||= Insert.new
|
40
|
+
count_executions(&block)
|
41
|
+
ensure
|
42
|
+
if @executions.zero?
|
43
|
+
Thread.current[:mongoid_batch_insert] = nil
|
44
|
+
raise_mixed if embedded?
|
45
|
+
inserter.execute(collection)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Execute the block, incrementing the executions before the call and
|
50
|
+
# decrementing them after in order to be able to nest blocks within
|
51
|
+
# each other.
|
52
|
+
#
|
53
|
+
# @todo Durran: Combine common code with embedded atomics.
|
54
|
+
#
|
55
|
+
# @example Execute and increment.
|
56
|
+
# execute { block.call }
|
57
|
+
#
|
58
|
+
# @param [ Proc ] block The block to call.
|
59
|
+
#
|
60
|
+
# @since 2.0.2, batch-relational-insert
|
61
|
+
def count_executions
|
62
|
+
@executions ||= 0
|
63
|
+
@executions += 1
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
@executions -=1
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid #:nodoc:
|
3
|
+
module Relations #:nodoc:
|
4
|
+
module Referenced #:nodoc:
|
5
|
+
module Batch #:nodoc:
|
6
|
+
|
7
|
+
# Handles all the batch insert collection.
|
8
|
+
class Insert
|
9
|
+
attr_accessor :documents, :options
|
10
|
+
|
11
|
+
# Consumes an execution that was supposed to hit the database, but is
|
12
|
+
# now being deferred to later in favor of a single batch insert.
|
13
|
+
#
|
14
|
+
# @example Consume the operation.
|
15
|
+
# set.consume({ "field" => "value" }, { :safe => true })
|
16
|
+
#
|
17
|
+
# @param [ Hash ] document The document to collect.
|
18
|
+
# @param [ Hash ] options The persistence options.
|
19
|
+
#
|
20
|
+
# @option options [ true, false ] :safe Persist in safe mode.
|
21
|
+
#
|
22
|
+
# @since 2.0.2, batch-relational-insert
|
23
|
+
def consume(document, options = {})
|
24
|
+
@consumed, @options = true, options
|
25
|
+
(@documents ||= []).push(document)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Has this operation consumed any executions?
|
29
|
+
#
|
30
|
+
# @example Is this consumed?
|
31
|
+
# insert.consumed?
|
32
|
+
#
|
33
|
+
# @return [ true, false ] If the operation has consumed anything.
|
34
|
+
#
|
35
|
+
# @since 2.0.2, batch-relational-insert
|
36
|
+
def consumed?
|
37
|
+
!!@consumed
|
38
|
+
end
|
39
|
+
|
40
|
+
# Execute the batch insert operation on the collection.
|
41
|
+
#
|
42
|
+
# @example Execute the operation.
|
43
|
+
# insert.execute(collection)
|
44
|
+
#
|
45
|
+
# @param [ Collection ] collection The root collection.
|
46
|
+
#
|
47
|
+
# @since 2.0.2, batch-relational-insert
|
48
|
+
def execute(collection)
|
49
|
+
if collection && consumed?
|
50
|
+
collection.insert(documents, options)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -6,6 +6,33 @@ module Mongoid #:nodoc:
|
|
6
6
|
# This class defines the behaviour for all relations that are a
|
7
7
|
# one-to-many between documents in different collections.
|
8
8
|
class Many < Relations::Many
|
9
|
+
include Batch
|
10
|
+
|
11
|
+
# Appends a document or array of documents to the relation. Will set
|
12
|
+
# the parent and update the index in the process.
|
13
|
+
#
|
14
|
+
# @example Append a document.
|
15
|
+
# person.posts << post
|
16
|
+
#
|
17
|
+
# @example Push a document.
|
18
|
+
# person.posts.push(post)
|
19
|
+
#
|
20
|
+
# @example Concat with other documents.
|
21
|
+
# person.posts.concat([ post_one, post_two ])
|
22
|
+
#
|
23
|
+
# @param [ Document, Array<Document> ] *args Any number of documents.
|
24
|
+
def <<(*args)
|
25
|
+
options = default_options(args)
|
26
|
+
batched do
|
27
|
+
args.flatten.each do |doc|
|
28
|
+
return doc unless doc
|
29
|
+
append(doc, options)
|
30
|
+
doc.save if base.persisted? && !options[:binding]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
alias :concat :<<
|
35
|
+
alias :push :<<
|
9
36
|
|
10
37
|
# Binds the base object to the inverse of the relation. This is so we
|
11
38
|
# are referenced to the actual objects themselves and dont hit the
|
@@ -286,6 +313,38 @@ module Mongoid #:nodoc:
|
|
286
313
|
Bindings::Referenced::Many.new(base, new_target || target, metadata)
|
287
314
|
end
|
288
315
|
|
316
|
+
# Get the collection of the relation in question.
|
317
|
+
#
|
318
|
+
# @example Get the collection of the relation.
|
319
|
+
# relation.collection
|
320
|
+
#
|
321
|
+
# @return [ Collection ] The collection of the relation.
|
322
|
+
#
|
323
|
+
# @since 2.0.2, batch-relational-insert
|
324
|
+
def collection
|
325
|
+
metadata.klass.collection
|
326
|
+
end
|
327
|
+
|
328
|
+
# Get the value for the foreign key in convertable or unconvertable
|
329
|
+
# form.
|
330
|
+
#
|
331
|
+
# @todo Durran: Find a common place for this.
|
332
|
+
#
|
333
|
+
# @example Get the value.
|
334
|
+
# relation.convertable
|
335
|
+
#
|
336
|
+
# @return [ String, Unconvertable, BSON::ObjectId ] The string or object id.
|
337
|
+
#
|
338
|
+
# @since 2.0.2
|
339
|
+
def convertable
|
340
|
+
inverse = metadata.inverse_klass
|
341
|
+
if inverse.using_object_ids? || base.id.is_a?(BSON::ObjectId)
|
342
|
+
base.id
|
343
|
+
else
|
344
|
+
Mongoid::Criterion::Unconvertable.new(base.id)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
289
348
|
# Returns the criteria object for the target class with its documents set
|
290
349
|
# to target.
|
291
350
|
#
|
@@ -295,7 +354,7 @@ module Mongoid #:nodoc:
|
|
295
354
|
# @return [ Criteria ] A new criteria.
|
296
355
|
def criteria
|
297
356
|
raise_mixed if klass.embedded?
|
298
|
-
metadata.klass.where(metadata.foreign_key =>
|
357
|
+
metadata.klass.where(metadata.foreign_key => convertable)
|
299
358
|
end
|
300
359
|
|
301
360
|
# Tells if the target array been initialized.
|
@@ -341,7 +400,7 @@ module Mongoid #:nodoc:
|
|
341
400
|
load!(:binding => true) and return super if [].respond_to?(name)
|
342
401
|
klass = metadata.klass
|
343
402
|
klass.send(:with_scope, criteria) do
|
344
|
-
criteria.send(name, *args)
|
403
|
+
criteria.send(name, *args, &block)
|
345
404
|
end
|
346
405
|
end
|
347
406
|
|