mongoid 2.1.9 → 2.2.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 +281 -0
- data/{README.rdoc → README.md} +24 -14
- data/Rakefile +1 -1
- data/lib/config/locales/bg.yml +5 -0
- data/lib/config/locales/de.yml +5 -0
- data/lib/config/locales/en-GB.yml +5 -0
- data/lib/config/locales/en.yml +5 -0
- data/lib/config/locales/es.yml +3 -0
- data/lib/config/locales/fr.yml +5 -0
- data/lib/config/locales/hi.yml +5 -0
- data/lib/config/locales/hu.yml +5 -0
- data/lib/config/locales/id.yml +5 -0
- data/lib/config/locales/it.yml +5 -0
- data/lib/config/locales/ja.yml +5 -0
- data/lib/config/locales/kr.yml +5 -0
- data/lib/config/locales/nl.yml +5 -0
- data/lib/config/locales/pl.yml +5 -0
- data/lib/config/locales/pt-BR.yml +5 -0
- data/lib/config/locales/pt.yml +5 -0
- data/lib/config/locales/ro.yml +5 -0
- data/lib/config/locales/ru.yml +5 -0
- data/lib/config/locales/sv.yml +5 -0
- data/lib/config/locales/vi.yml +5 -0
- data/lib/config/locales/zh-CN.yml +5 -0
- data/lib/mongoid/atomic.rb +61 -10
- data/lib/mongoid/atomic/modifiers.rb +156 -24
- data/lib/mongoid/attributes.rb +38 -10
- data/lib/mongoid/collection.rb +21 -3
- data/lib/mongoid/collections.rb +52 -6
- data/lib/mongoid/collections/master.rb +8 -2
- data/lib/mongoid/collections/operations.rb +1 -0
- data/lib/mongoid/config.rb +5 -2
- data/lib/mongoid/config/database.rb +15 -2
- data/lib/mongoid/contexts/mongo.rb +3 -0
- data/lib/mongoid/criteria.rb +27 -3
- data/lib/mongoid/criterion/inclusion.rb +58 -0
- data/lib/mongoid/dirty.rb +2 -0
- data/lib/mongoid/document.rb +23 -0
- data/lib/mongoid/errors.rb +3 -0
- data/lib/mongoid/errors/callback.rb +26 -0
- data/lib/mongoid/errors/eager_load.rb +25 -0
- data/lib/mongoid/errors/invalid_find.rb +19 -0
- data/lib/mongoid/extensions.rb +3 -1
- data/lib/mongoid/extensions/object_id/conversions.rb +1 -1
- data/lib/mongoid/extras.rb +12 -2
- data/lib/mongoid/fields.rb +41 -2
- data/lib/mongoid/fields/serializable.rb +36 -0
- data/lib/mongoid/fields/serializable/foreign_keys/array.rb +13 -14
- data/lib/mongoid/fields/serializable/foreign_keys/object.rb +13 -14
- data/lib/mongoid/finders.rb +4 -4
- data/lib/mongoid/identity_map.rb +33 -20
- data/lib/mongoid/keys.rb +24 -1
- data/lib/mongoid/nested_attributes.rb +16 -4
- data/lib/mongoid/persistence.rb +50 -6
- data/lib/mongoid/persistence/operations.rb +1 -4
- data/lib/mongoid/persistence/operations/update.rb +3 -1
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +27 -44
- data/lib/mongoid/relations/builders/referenced/many.rb +2 -1
- data/lib/mongoid/relations/builders/referenced/one.rb +1 -1
- data/lib/mongoid/relations/cascading.rb +12 -1
- data/lib/mongoid/relations/embedded/many.rb +11 -4
- data/lib/mongoid/relations/embedded/one.rb +6 -2
- data/lib/mongoid/relations/macros.rb +19 -12
- data/lib/mongoid/relations/metadata.rb +17 -0
- data/lib/mongoid/relations/polymorphic.rb +12 -1
- data/lib/mongoid/relations/proxy.rb +24 -0
- data/lib/mongoid/relations/referenced/in.rb +20 -0
- data/lib/mongoid/relations/referenced/many.rb +30 -6
- data/lib/mongoid/relations/referenced/many_to_many.rb +18 -2
- data/lib/mongoid/relations/referenced/one.rb +19 -0
- data/lib/mongoid/relations/reflections.rb +23 -3
- data/lib/mongoid/relations/targets/enumerable.rb +29 -1
- data/lib/mongoid/serialization.rb +1 -1
- data/lib/mongoid/sharding.rb +12 -2
- data/lib/mongoid/threaded.rb +98 -0
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +12 -2
- metadata +25 -21
data/lib/mongoid/attributes.rb
CHANGED
@@ -25,6 +25,7 @@ module Mongoid #:nodoc:
|
|
25
25
|
attribute = read_attribute(name)
|
26
26
|
! attribute.blank? || attribute == false
|
27
27
|
end
|
28
|
+
alias :has_attribute? :attribute_present?
|
28
29
|
|
29
30
|
# Read a value from the document attributes. If the value does not exist
|
30
31
|
# it will return nil.
|
@@ -55,9 +56,11 @@ module Mongoid #:nodoc:
|
|
55
56
|
#
|
56
57
|
# @since 1.0.0
|
57
58
|
def remove_attribute(name)
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
assigning do
|
60
|
+
access = name.to_s
|
61
|
+
attribute_will_change!(access)
|
62
|
+
attributes.delete(access)
|
63
|
+
end
|
61
64
|
end
|
62
65
|
|
63
66
|
# Override respond_to? so it responds properly for dynamic attributes.
|
@@ -92,12 +95,14 @@ module Mongoid #:nodoc:
|
|
92
95
|
#
|
93
96
|
# @since 1.0.0
|
94
97
|
def write_attribute(name, value)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
98
|
+
assigning do
|
99
|
+
access = name.to_s
|
100
|
+
typed_value_for(access, value).tap do |value|
|
101
|
+
unless attributes[access] == value || attribute_changed?(access)
|
102
|
+
attribute_will_change!(access)
|
103
|
+
end
|
104
|
+
attributes[access] = value
|
99
105
|
end
|
100
|
-
attributes[access] = value
|
101
106
|
end
|
102
107
|
end
|
103
108
|
alias :[]= :write_attribute
|
@@ -117,8 +122,10 @@ module Mongoid #:nodoc:
|
|
117
122
|
#
|
118
123
|
# @since 1.0.0
|
119
124
|
def write_attributes(attrs = nil, guard_protected_attributes = true)
|
120
|
-
|
121
|
-
|
125
|
+
assigning do
|
126
|
+
process(attrs, guard_protected_attributes) do |document|
|
127
|
+
document.identify if new? && id.blank?
|
128
|
+
end
|
122
129
|
end
|
123
130
|
end
|
124
131
|
alias :attributes= :write_attributes
|
@@ -145,6 +152,27 @@ module Mongoid #:nodoc:
|
|
145
152
|
end
|
146
153
|
end
|
147
154
|
|
155
|
+
# Begin the assignment of attributes. While in this block embedded
|
156
|
+
# documents will not autosave themselves in order to allow the document to
|
157
|
+
# be in a valid state.
|
158
|
+
#
|
159
|
+
# @example Execute the assignment.
|
160
|
+
# assigning do
|
161
|
+
# person.attributes = { :addresses => [ address ] }
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# @return [ Object ] The yielded value.
|
165
|
+
#
|
166
|
+
# @since 2.2.0
|
167
|
+
def assigning
|
168
|
+
begin
|
169
|
+
Threaded.begin_assign
|
170
|
+
yield
|
171
|
+
ensure
|
172
|
+
Threaded.exit_assign
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
148
176
|
# Used for allowing accessor methods for dynamic attributes.
|
149
177
|
#
|
150
178
|
# @param [ String, Symbol ] name The name of the method.
|
data/lib/mongoid/collection.rb
CHANGED
@@ -17,6 +17,18 @@ module Mongoid #:nodoc
|
|
17
17
|
# collection.save({ :name => "Al" })
|
18
18
|
delegate *(Collections::Operations::PROXIED.dup << {:to => :master})
|
19
19
|
|
20
|
+
# Get the unwrapped driver collection for this mongoid collection.
|
21
|
+
#
|
22
|
+
# @example Get the driver collection.
|
23
|
+
# collection.driver
|
24
|
+
#
|
25
|
+
# @return [ Mongo::Collection ] The driver collection.
|
26
|
+
#
|
27
|
+
# @since 2.2.0
|
28
|
+
def driver
|
29
|
+
master.collection
|
30
|
+
end
|
31
|
+
|
20
32
|
# Find documents from the database given a selector and options.
|
21
33
|
#
|
22
34
|
# @example Find documents in the collection.
|
@@ -56,8 +68,14 @@ module Mongoid #:nodoc
|
|
56
68
|
#
|
57
69
|
# @param [ Class ] klass The class the collection is for.
|
58
70
|
# @param [ String ] name The name of the collection.
|
59
|
-
|
60
|
-
|
71
|
+
# @param [ Hash ] options The collection options.
|
72
|
+
#
|
73
|
+
# @option options [ true, false ] :capped If the collection is capped.
|
74
|
+
# @option options [ Integer ] :size The capped collection size.
|
75
|
+
# @option options [ Integer ] :max The maximum number of docs in the
|
76
|
+
# capped collection.
|
77
|
+
def initialize(klass, name, options = {})
|
78
|
+
@klass, @name, @options = klass, name, options || {}
|
61
79
|
end
|
62
80
|
|
63
81
|
# Inserts one or more documents in the collection.
|
@@ -106,7 +124,7 @@ module Mongoid #:nodoc
|
|
106
124
|
def master(options = {})
|
107
125
|
options.delete(:cache)
|
108
126
|
db = Mongoid.databases[klass.database] || Mongoid.master
|
109
|
-
@master ||= Collections::Master.new(db, @name)
|
127
|
+
@master ||= Collections::Master.new(db, @name, @options)
|
110
128
|
end
|
111
129
|
|
112
130
|
# Updates one or more documents in the collection.
|
data/lib/mongoid/collections.rb
CHANGED
@@ -6,13 +6,41 @@ module Mongoid #:nodoc
|
|
6
6
|
module Collections
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
-
delegate :collection, :db, :to => "self.class"
|
10
|
-
|
11
9
|
included do
|
12
10
|
cattr_accessor :_collection, :collection_name
|
13
11
|
self.collection_name = self.name.collectionize
|
14
12
|
end
|
15
13
|
|
14
|
+
# Get the collection for the class.
|
15
|
+
#
|
16
|
+
# @note Defining methods instead of delegate to avoid calls to
|
17
|
+
# Kernel.caller for class load performance reasons.
|
18
|
+
#
|
19
|
+
# @example Get the collection.
|
20
|
+
# person.collection
|
21
|
+
#
|
22
|
+
# @return [ Collection ] The class collection.
|
23
|
+
#
|
24
|
+
# @since 1.0.0
|
25
|
+
def collection
|
26
|
+
self.class.collection
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get the database for the class.
|
30
|
+
#
|
31
|
+
# @note Defining methods instead of delegate to avoid calls to
|
32
|
+
# Kernel.caller for class load performance reasons.
|
33
|
+
#
|
34
|
+
# @example Get the database.
|
35
|
+
# person.db
|
36
|
+
#
|
37
|
+
# @return [ DB ] The class db.
|
38
|
+
#
|
39
|
+
# @since 1.0.0
|
40
|
+
def db
|
41
|
+
self.class.db
|
42
|
+
end
|
43
|
+
|
16
44
|
module ClassMethods #:nodoc:
|
17
45
|
|
18
46
|
# Returns the collection associated with this +Document+. If the
|
@@ -53,9 +81,20 @@ module Mongoid #:nodoc
|
|
53
81
|
#
|
54
82
|
# @example Store in a separate collection than the default.
|
55
83
|
# Model.store_in :population
|
56
|
-
|
84
|
+
#
|
85
|
+
# @example Store in a capped collection.
|
86
|
+
# Model.store_in :population, :capped => true, :max => 10000
|
87
|
+
#
|
88
|
+
# @param [ Symbol ] name The name of the collection.
|
89
|
+
# @param [ Hash ] options The collection options.
|
90
|
+
#
|
91
|
+
# @option options [ true, false ] :capped If the collection is capped.
|
92
|
+
# @option options [ Integer ] :size The capped collection size.
|
93
|
+
# @option options [ Integer ] :max The maximum number of docs in the
|
94
|
+
# capped collection.
|
95
|
+
def store_in(name, options = {})
|
57
96
|
self.collection_name = name.to_s
|
58
|
-
set_collection
|
97
|
+
set_collection(options)
|
59
98
|
end
|
60
99
|
|
61
100
|
protected
|
@@ -65,9 +104,16 @@ module Mongoid #:nodoc
|
|
65
104
|
# @example Set the collection.
|
66
105
|
# Model.set_collection
|
67
106
|
#
|
107
|
+
# @param [ Hash ] options The collection options.
|
108
|
+
#
|
109
|
+
# @option options [ true, false ] :capped If the collection is capped.
|
110
|
+
# @option options [ Integer ] :size The capped collection size.
|
111
|
+
# @option options [ Integer ] :max The maximum number of docs in the
|
112
|
+
# capped collection.
|
113
|
+
|
68
114
|
# @return [ Collection ] The Mongoid collection wrapper.
|
69
|
-
def set_collection
|
70
|
-
self._collection =
|
115
|
+
def set_collection(options = {})
|
116
|
+
self._collection = Collection.new(self, self.collection_name, options)
|
71
117
|
end
|
72
118
|
end
|
73
119
|
end
|
@@ -31,8 +31,14 @@ module Mongoid #:nodoc:
|
|
31
31
|
#
|
32
32
|
# @param [ Mongo::DB ] master The master database.
|
33
33
|
# @param [ String ] name The name of the database.
|
34
|
-
|
35
|
-
|
34
|
+
# @param [ Hash ] options The collection options.
|
35
|
+
#
|
36
|
+
# @option options [ true, false ] :capped If the collection is capped.
|
37
|
+
# @option options [ Integer ] :size The capped collection size.
|
38
|
+
# @option options [ Integer ] :max The maximum number of docs in the
|
39
|
+
# capped collection.
|
40
|
+
def initialize(master, name, options = {})
|
41
|
+
@collection = master.create_collection(name, options)
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
data/lib/mongoid/config.rb
CHANGED
@@ -166,7 +166,10 @@ module Mongoid #:nodoc
|
|
166
166
|
#
|
167
167
|
# @return [ Logger ] The newly set logger.
|
168
168
|
def logger=(logger)
|
169
|
-
|
169
|
+
case logger
|
170
|
+
when Logger then @logger = logger
|
171
|
+
when false, nil then @logger = nil
|
172
|
+
end
|
170
173
|
end
|
171
174
|
|
172
175
|
# Purge all data in all collections, including indexes.
|
@@ -202,7 +205,7 @@ module Mongoid #:nodoc
|
|
202
205
|
# set is not a valid +Mongo::DB+, then an error will be raised.
|
203
206
|
#
|
204
207
|
# @example Set the master database.
|
205
|
-
# config.master = Mongo::Connection.db("test")
|
208
|
+
# config.master = Mongo::Connection.new.db("test")
|
206
209
|
#
|
207
210
|
# @param [ Mongo::DB ] db The master database.
|
208
211
|
#
|
@@ -7,7 +7,7 @@ module Mongoid #:nodoc:
|
|
7
7
|
class Database < Hash
|
8
8
|
|
9
9
|
# keys to remove from self to not pass through to Mongo::Connection
|
10
|
-
PRIVATE_OPTIONS = %w(uri database username password)
|
10
|
+
PRIVATE_OPTIONS = %w(uri database username password logger)
|
11
11
|
|
12
12
|
# Configure the database connections. This will return an array
|
13
13
|
# containing the master and an array of slaves.
|
@@ -108,6 +108,19 @@ module Mongoid #:nodoc:
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
+
# Should we use a logger?
|
112
|
+
#
|
113
|
+
# @example Should we use a logger?
|
114
|
+
# database.logger?
|
115
|
+
#
|
116
|
+
# @return [ true, false ] Defaults to true, false if specifically
|
117
|
+
# defined.
|
118
|
+
#
|
119
|
+
# @since 2.2.0
|
120
|
+
def logger?
|
121
|
+
self[:logger].nil? || self[:logger] ? true : false
|
122
|
+
end
|
123
|
+
|
111
124
|
# Convenience for accessing the hash via dot notation.
|
112
125
|
#
|
113
126
|
# @example Access a value in alternate syntax.
|
@@ -147,7 +160,7 @@ module Mongoid #:nodoc:
|
|
147
160
|
def optional(slave = false)
|
148
161
|
({
|
149
162
|
:pool_size => pool_size,
|
150
|
-
:logger => Mongoid::Logger.new,
|
163
|
+
:logger => logger? ? Mongoid::Logger.new : nil,
|
151
164
|
:slave_ok => slave
|
152
165
|
}).merge(self).reject { |k,v| PRIVATE_OPTIONS.include? k }.
|
153
166
|
inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo} # mongo likes symbols
|
@@ -140,6 +140,9 @@ module Mongoid #:nodoc:
|
|
140
140
|
#
|
141
141
|
# @return [ Cursor ] An enumerable +Cursor+ of results.
|
142
142
|
def execute
|
143
|
+
criteria.inclusions.reject! do |metadata|
|
144
|
+
metadata.eager_load(criteria)
|
145
|
+
end
|
143
146
|
klass.collection.find(selector, process_options) || []
|
144
147
|
end
|
145
148
|
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -32,7 +32,6 @@ module Mongoid #:nodoc:
|
|
32
32
|
include Criterion::Optional
|
33
33
|
|
34
34
|
attr_accessor \
|
35
|
-
:collection,
|
36
35
|
:documents,
|
37
36
|
:embedded,
|
38
37
|
:ids,
|
@@ -109,6 +108,18 @@ module Mongoid #:nodoc:
|
|
109
108
|
end
|
110
109
|
end
|
111
110
|
|
111
|
+
# Get the collection associated with the criteria.
|
112
|
+
#
|
113
|
+
# @example Get the collection.
|
114
|
+
# criteria.collection
|
115
|
+
#
|
116
|
+
# @return [ Collection ] The collection.
|
117
|
+
#
|
118
|
+
# @since 2.2.0
|
119
|
+
def collection
|
120
|
+
klass.collection
|
121
|
+
end
|
122
|
+
|
112
123
|
# Return or create the context in which this criteria should be executed.
|
113
124
|
#
|
114
125
|
# This will return an Enumerable context if the class is embedded,
|
@@ -154,7 +165,7 @@ module Mongoid #:nodoc:
|
|
154
165
|
#
|
155
166
|
# @since 2.0.0
|
156
167
|
def freeze
|
157
|
-
context and super
|
168
|
+
context and inclusions and super
|
158
169
|
end
|
159
170
|
|
160
171
|
# Merges the supplied argument hash into a single criteria
|
@@ -298,7 +309,7 @@ module Mongoid #:nodoc:
|
|
298
309
|
#
|
299
310
|
# @since 2.0.0
|
300
311
|
def raise_invalid
|
301
|
-
raise Errors::
|
312
|
+
raise Errors::InvalidFind.new
|
302
313
|
end
|
303
314
|
|
304
315
|
protected
|
@@ -316,6 +327,18 @@ module Mongoid #:nodoc:
|
|
316
327
|
other.is_a?(Criteria) ? other.entries : other
|
317
328
|
end
|
318
329
|
|
330
|
+
# Get the raw driver collection from the criteria.
|
331
|
+
#
|
332
|
+
# @example Get the raw driver collection.
|
333
|
+
# criteria.driver
|
334
|
+
#
|
335
|
+
# @return [ Mongo::Collection ] The driver collection.
|
336
|
+
#
|
337
|
+
# @since 2.2.0
|
338
|
+
def driver
|
339
|
+
collection.driver
|
340
|
+
end
|
341
|
+
|
319
342
|
# Clone or dup the current +Criteria+. This will return a new criteria with
|
320
343
|
# the selector, options, klass, embedded options, etc intact.
|
321
344
|
#
|
@@ -331,6 +354,7 @@ module Mongoid #:nodoc:
|
|
331
354
|
def initialize_copy(other)
|
332
355
|
@selector = other.selector.dup
|
333
356
|
@options = other.options.dup
|
357
|
+
@includes = other.inclusions.dup
|
334
358
|
@context = nil
|
335
359
|
end
|
336
360
|
|
@@ -125,6 +125,64 @@ module Mongoid #:nodoc:
|
|
125
125
|
end
|
126
126
|
alias :any_in :in
|
127
127
|
|
128
|
+
# Eager loads all the provided relations. Will load all the documents
|
129
|
+
# into the identity map who's ids match based on the extra query for the
|
130
|
+
# ids.
|
131
|
+
#
|
132
|
+
# @note This will only work if Mongoid's identity map is enabled. To do
|
133
|
+
# so set identity_map_enabled: true in your mongoid.yml
|
134
|
+
#
|
135
|
+
# @note This will work for embedded relations that reference another
|
136
|
+
# collection via belongs_to as well.
|
137
|
+
#
|
138
|
+
# @note Eager loading brings all the documents into memory, so there is a
|
139
|
+
# sweet spot on the performance gains. Internal benchmarks show that
|
140
|
+
# eager loading becomes slower around 100k documents, but this will
|
141
|
+
# naturally depend on the specific application.
|
142
|
+
#
|
143
|
+
# @example Eager load the provided relations.
|
144
|
+
# Person.includes(:posts, :game)
|
145
|
+
#
|
146
|
+
# @param [ Array<Symbol> ] relations The names of the relations to eager
|
147
|
+
# load.
|
148
|
+
#
|
149
|
+
# @return [ Criteria ] The cloned criteria.
|
150
|
+
#
|
151
|
+
# @since 2.2.0
|
152
|
+
def includes(*relations)
|
153
|
+
relations.each do |name|
|
154
|
+
inclusions.push(klass.reflect_on_association(name))
|
155
|
+
end
|
156
|
+
clone
|
157
|
+
end
|
158
|
+
|
159
|
+
# Get a list of criteria that are to be executed for eager loading.
|
160
|
+
#
|
161
|
+
# @example Get the eager loading inclusions.
|
162
|
+
# Person.includes(:game).inclusions
|
163
|
+
#
|
164
|
+
# @return [ Array<Metadata> ] The inclusions.
|
165
|
+
#
|
166
|
+
# @since 2.2.0
|
167
|
+
def inclusions
|
168
|
+
@inclusions ||= []
|
169
|
+
end
|
170
|
+
|
171
|
+
# Loads an array of ids only for the current criteria. Used by eager
|
172
|
+
# loading to determine the documents to load.
|
173
|
+
#
|
174
|
+
# @example Load the related ids.
|
175
|
+
# criteria.load_ids("person_id")
|
176
|
+
#
|
177
|
+
# @param [ String ] key The id or foriegn key string.
|
178
|
+
#
|
179
|
+
# @return [ Array<String, BSON::ObjectId> ] The ids to load.
|
180
|
+
#
|
181
|
+
# @since 2.2.0
|
182
|
+
def load_ids(key)
|
183
|
+
driver.find(selector, { :fields => { key => 1 }}).map { |doc| doc[key] }
|
184
|
+
end
|
185
|
+
|
128
186
|
# Adds a criterion to the +Criteria+ that specifies values to do
|
129
187
|
# geospacial searches by. The field must be indexed with the "2d" option.
|
130
188
|
#
|