mongoid 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|