mongoid 2.3.1 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +34 -1
- data/lib/mongoid.rb +3 -2
- data/lib/mongoid/atomic.rb +23 -2
- data/lib/mongoid/attributes.rb +0 -21
- data/lib/mongoid/callbacks.rb +9 -1
- data/lib/mongoid/components.rb +2 -0
- data/lib/mongoid/config.rb +4 -2
- data/lib/mongoid/contexts/mongo.rb +19 -8
- data/lib/mongoid/criterion/inclusion.rb +6 -4
- data/lib/mongoid/dirty.rb +1 -0
- data/lib/mongoid/document.rb +1 -25
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +13 -0
- data/lib/mongoid/extensions/object/yoda.rb +1 -0
- data/lib/mongoid/matchers/strategies.rb +6 -1
- data/lib/mongoid/persistence.rb +2 -21
- data/lib/mongoid/railtie.rb +8 -1
- data/lib/mongoid/relations/accessors.rb +7 -5
- data/lib/mongoid/relations/binding.rb +2 -29
- data/lib/mongoid/relations/bindings/embedded/in.rb +4 -4
- data/lib/mongoid/relations/bindings/embedded/many.rb +4 -4
- data/lib/mongoid/relations/bindings/embedded/one.rb +4 -4
- data/lib/mongoid/relations/bindings/referenced/in.rb +4 -4
- data/lib/mongoid/relations/bindings/referenced/many.rb +4 -4
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
- data/lib/mongoid/relations/bindings/referenced/one.rb +4 -4
- data/lib/mongoid/relations/builder.rb +18 -4
- data/lib/mongoid/relations/builders.rb +0 -17
- data/lib/mongoid/relations/builders/embedded/in.rb +3 -3
- data/lib/mongoid/relations/builders/embedded/many.rb +4 -4
- data/lib/mongoid/relations/builders/embedded/one.rb +3 -3
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +1 -1
- data/lib/mongoid/relations/builders/referenced/one.rb +1 -0
- data/lib/mongoid/relations/embedded/in.rb +4 -3
- data/lib/mongoid/relations/embedded/many.rb +6 -5
- data/lib/mongoid/relations/embedded/one.rb +4 -3
- data/lib/mongoid/relations/metadata.rb +20 -5
- data/lib/mongoid/relations/proxy.rb +1 -48
- data/lib/mongoid/relations/referenced/in.rb +4 -3
- data/lib/mongoid/relations/referenced/many.rb +4 -3
- data/lib/mongoid/relations/referenced/many_to_many.rb +5 -4
- data/lib/mongoid/relations/referenced/one.rb +4 -3
- data/lib/mongoid/reloading.rb +91 -0
- data/lib/mongoid/state.rb +15 -22
- data/lib/mongoid/threaded.rb +51 -0
- data/lib/mongoid/threaded/lifecycle.rb +163 -0
- data/lib/mongoid/version.rb +1 -1
- metadata +21 -19
data/CHANGELOG.md
CHANGED
@@ -8,7 +8,40 @@ For instructions on upgrading to newer versions, visit
|
|
8
8
|
* Ranges can now be passed to #where criteria to create a $gte/$lte query under the
|
9
9
|
covers. `Person.where(dob: start_date...end_date)`
|
10
10
|
|
11
|
-
## 2.3.
|
11
|
+
## 2.3.2 \[ In Development \] \[ Branch: 2.3.0-stable \]
|
12
|
+
|
13
|
+
* \#1347 Fix embedded matchers when provided a hash value that does not have a
|
14
|
+
modifier as a key.
|
15
|
+
|
16
|
+
* \#1346 Dup default sorting criteria when calling first/last on a criteria.
|
17
|
+
|
18
|
+
* \#1343 When passing no arguments to `Criteria#all_of` return all documents.
|
19
|
+
(Chris Leishman)
|
20
|
+
|
21
|
+
* \#1339 Ensure destroy callbacks are run on cascadable children when deleting via
|
22
|
+
nested attributes.
|
23
|
+
|
24
|
+
* \#1324 Setting `inverse_of: nil` on a many-to-many referencing the same class
|
25
|
+
returns nil for the inverse foreign key.
|
26
|
+
|
27
|
+
* \#1323 Allow both strings and symbols as ids in the attributes array for
|
28
|
+
nested attributes. (Michael Wood)
|
29
|
+
|
30
|
+
* \#1312 Setting a logger on the config now accepts anything that quacks like a
|
31
|
+
logger.
|
32
|
+
|
33
|
+
* \#1297 Don't hit the database when accessing relations if the base is new.
|
34
|
+
|
35
|
+
* \#1239 Allow appending of referenced relations in create blocks, post default set.
|
36
|
+
|
37
|
+
* \#1236 Ensure all models are loaded in rake tasks, so even in threadsafe mode
|
38
|
+
all indexes can be created.
|
39
|
+
|
40
|
+
* \#736 Calling #reload on embedded documents now works properly.
|
41
|
+
|
42
|
+
### Resolved Issues
|
43
|
+
|
44
|
+
## 2.3.1
|
12
45
|
|
13
46
|
### Resolved Issues
|
14
47
|
|
data/lib/mongoid.rb
CHANGED
@@ -28,10 +28,10 @@ require "active_support/inflector"
|
|
28
28
|
require "active_support/time_with_zone"
|
29
29
|
require "active_model"
|
30
30
|
require "mongo"
|
31
|
-
require "mongoid/errors"
|
32
31
|
require "mongoid/extensions"
|
33
|
-
require "mongoid/
|
32
|
+
require "mongoid/errors"
|
34
33
|
require "mongoid/threaded"
|
34
|
+
require "mongoid/relations"
|
35
35
|
require "mongoid/atomic"
|
36
36
|
require "mongoid/attributes"
|
37
37
|
require "mongoid/callbacks"
|
@@ -64,6 +64,7 @@ require "mongoid/named_scope"
|
|
64
64
|
require "mongoid/nested_attributes"
|
65
65
|
require "mongoid/observer"
|
66
66
|
require "mongoid/persistence"
|
67
|
+
require "mongoid/reloading"
|
67
68
|
require "mongoid/safety"
|
68
69
|
require "mongoid/scope"
|
69
70
|
require "mongoid/serialization"
|
data/lib/mongoid/atomic.rb
CHANGED
@@ -101,7 +101,15 @@ module Mongoid #:nodoc:
|
|
101
101
|
#
|
102
102
|
# @since 2.2.0
|
103
103
|
def atomic_pulls
|
104
|
-
|
104
|
+
delayed_atomic_pulls.inject({}) do |pulls, (name, docs)|
|
105
|
+
pulls.tap do |pull|
|
106
|
+
docs.each do |doc|
|
107
|
+
(pull[doc.atomic_path] ||= []).push(doc.as_document)
|
108
|
+
doc.destroyed = true
|
109
|
+
doc.flagged_for_destroy = false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
105
113
|
end
|
106
114
|
|
107
115
|
# Add the document as an atomic pull.
|
@@ -113,7 +121,8 @@ module Mongoid #:nodoc:
|
|
113
121
|
#
|
114
122
|
# @since 2.2.0
|
115
123
|
def add_atomic_pull(document)
|
116
|
-
|
124
|
+
document.flagged_for_destroy = true
|
125
|
+
(delayed_atomic_pulls[document.metadata.name.to_s] ||= []).push(document)
|
117
126
|
end
|
118
127
|
|
119
128
|
# Get all the push attributes that need to occur.
|
@@ -175,6 +184,18 @@ module Mongoid #:nodoc:
|
|
175
184
|
@delayed_atomic_sets ||= {}
|
176
185
|
end
|
177
186
|
|
187
|
+
# Get a hash of atomic pulls that are pending.
|
188
|
+
#
|
189
|
+
# @example Get the atomic pulls.
|
190
|
+
# document.delayed_atomic_pulls
|
191
|
+
#
|
192
|
+
# @return [ Hash ] name/document pairs.
|
193
|
+
#
|
194
|
+
# @since 2.3.2
|
195
|
+
def delayed_atomic_pulls
|
196
|
+
@delayed_atomic_pulls ||= {}
|
197
|
+
end
|
198
|
+
|
178
199
|
private
|
179
200
|
|
180
201
|
# Get the atomic paths utility for this document.
|
data/lib/mongoid/attributes.rb
CHANGED
@@ -175,27 +175,6 @@ module Mongoid #:nodoc:
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
# Begin the assignment of attributes. While in this block embedded
|
179
|
-
# documents will not autosave themselves in order to allow the document to
|
180
|
-
# be in a valid state.
|
181
|
-
#
|
182
|
-
# @example Execute the assignment.
|
183
|
-
# _assigning do
|
184
|
-
# person.attributes = { :addresses => [ address ] }
|
185
|
-
# end
|
186
|
-
#
|
187
|
-
# @return [ Object ] The yielded value.
|
188
|
-
#
|
189
|
-
# @since 2.2.0
|
190
|
-
def _assigning
|
191
|
-
begin
|
192
|
-
Threaded.begin_assign
|
193
|
-
yield
|
194
|
-
ensure
|
195
|
-
Threaded.exit_assign
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
178
|
# Used for allowing accessor methods for dynamic attributes.
|
200
179
|
#
|
201
180
|
# @param [ String, Symbol ] name The name of the method.
|
data/lib/mongoid/callbacks.rb
CHANGED
@@ -82,6 +82,8 @@ module Mongoid #:nodoc:
|
|
82
82
|
[].tap do |children|
|
83
83
|
relations.each_pair do |name, metadata|
|
84
84
|
next unless metadata.cascading_callbacks?
|
85
|
+
delayed_pulls = delayed_atomic_pulls[name]
|
86
|
+
children.concat(delayed_pulls) if delayed_pulls
|
85
87
|
child = send(name)
|
86
88
|
Array.wrap(child).each do |doc|
|
87
89
|
children.push(doc) if cascadable_child?(kind, doc)
|
@@ -121,7 +123,13 @@ module Mongoid #:nodoc:
|
|
121
123
|
#
|
122
124
|
# @since 2.3.0
|
123
125
|
def child_callback_type(kind, child)
|
124
|
-
kind == :update
|
126
|
+
if kind == :update
|
127
|
+
return :create if child.new_record?
|
128
|
+
return :destroy if child.flagged_for_destroy?
|
129
|
+
kind
|
130
|
+
else
|
131
|
+
kind
|
132
|
+
end
|
125
133
|
end
|
126
134
|
end
|
127
135
|
end
|
data/lib/mongoid/components.rb
CHANGED
@@ -34,10 +34,12 @@ module Mongoid #:nodoc
|
|
34
34
|
include Mongoid::NestedAttributes
|
35
35
|
include Mongoid::Persistence
|
36
36
|
include Mongoid::Relations
|
37
|
+
include Mongoid::Reloading
|
37
38
|
include Mongoid::Safety
|
38
39
|
include Mongoid::Serialization
|
39
40
|
include Mongoid::Sharding
|
40
41
|
include Mongoid::State
|
42
|
+
include Mongoid::Threaded::Lifecycle
|
41
43
|
include Mongoid::Timestamps::Timeless
|
42
44
|
include Mongoid::Validations
|
43
45
|
include Mongoid::Callbacks
|
data/lib/mongoid/config.rb
CHANGED
@@ -166,8 +166,10 @@ module Mongoid #:nodoc
|
|
166
166
|
# @return [ Logger ] The newly set logger.
|
167
167
|
def logger=(logger)
|
168
168
|
case logger
|
169
|
-
|
170
|
-
|
169
|
+
when false, nil then @logger = nil
|
170
|
+
when true then @logger = default_logger
|
171
|
+
else
|
172
|
+
@logger = logger if logger.respond_to?(:info)
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
@@ -158,10 +158,7 @@ module Mongoid #:nodoc:
|
|
158
158
|
#
|
159
159
|
# @return [ Document ] The first document in the collection.
|
160
160
|
def first
|
161
|
-
|
162
|
-
sorting = opts[:sort] ||= []
|
163
|
-
sorting << [:_id, :asc]
|
164
|
-
attributes = klass.collection.find_one(selector, opts)
|
161
|
+
attributes = klass.collection.find_one(selector, options_with_default_sorting)
|
165
162
|
attributes ? Mongoid::Factory.from_db(klass, attributes) : nil
|
166
163
|
end
|
167
164
|
alias :one :first
|
@@ -225,10 +222,8 @@ module Mongoid #:nodoc:
|
|
225
222
|
#
|
226
223
|
# @return [ Document ] The last document in the collection.
|
227
224
|
def last
|
228
|
-
opts =
|
229
|
-
|
230
|
-
sorting << [:_id, :asc]
|
231
|
-
opts[:sort] = sorting.map{ |option| [ option[0], option[1].invert ] }.uniq
|
225
|
+
opts = options_with_default_sorting
|
226
|
+
opts[:sort] = opts[:sort].map{ |option| [ option[0], option[1].invert ] }.uniq
|
232
227
|
attributes = klass.collection.find_one(selector, opts)
|
233
228
|
attributes ? Mongoid::Factory.from_db(klass, attributes) : nil
|
234
229
|
end
|
@@ -374,6 +369,22 @@ module Mongoid #:nodoc:
|
|
374
369
|
value && value.do_or_do_not(:nan?) ? nil : value
|
375
370
|
end
|
376
371
|
|
372
|
+
# Get the options hash with the default sorting options provided.
|
373
|
+
#
|
374
|
+
# @example Get the options.
|
375
|
+
# criteria.options_with_default_sorting
|
376
|
+
#
|
377
|
+
# @return [ Hash ] The options.
|
378
|
+
#
|
379
|
+
# @since 2.3.2
|
380
|
+
def options_with_default_sorting
|
381
|
+
process_options.tap do |opts|
|
382
|
+
sorting = opts[:sort] ? opts[:sort].dup : []
|
383
|
+
sorting << [:_id, :asc]
|
384
|
+
opts[:sort] = sorting
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
377
388
|
# Filters the field list. If no fields have been supplied, then it will be
|
378
389
|
# empty. If fields have been defined then _type will be included as well.
|
379
390
|
#
|
@@ -34,10 +34,12 @@ module Mongoid #:nodoc:
|
|
34
34
|
# @since 2.3.0
|
35
35
|
def all_of(*args)
|
36
36
|
clone.tap do |crit|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
unless args.empty?
|
38
|
+
criterion = @selector["$and"] || []
|
39
|
+
converted = BSON::ObjectId.convert(klass, args.flatten)
|
40
|
+
expanded = converted.collect { |hash| hash.expand_complex_criteria }
|
41
|
+
crit.selector["$and"] = criterion.concat(expanded)
|
42
|
+
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
data/lib/mongoid/dirty.rb
CHANGED
data/lib/mongoid/document.rb
CHANGED
@@ -129,38 +129,14 @@ module Mongoid #:nodoc:
|
|
129
129
|
@attributes ||= {}
|
130
130
|
options ||= {}
|
131
131
|
process(attrs, options[:as] || :default, !options[:without_protection]) do
|
132
|
-
yield self if block_given?
|
133
132
|
identify
|
134
133
|
apply_defaults
|
134
|
+
yield(self) if block_given?
|
135
135
|
end
|
136
136
|
run_callbacks(:initialize) { self }
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
# Reloads the +Document+ attributes from the database. If the document has
|
141
|
-
# not been saved then an error will get raised if the configuration option
|
142
|
-
# was set.
|
143
|
-
#
|
144
|
-
# @example Reload the document.
|
145
|
-
# person.reload
|
146
|
-
#
|
147
|
-
# @raise [ Errors::DocumentNotFound ] If the document was deleted.
|
148
|
-
#
|
149
|
-
# @return [ Document ] The document, reloaded.
|
150
|
-
def reload
|
151
|
-
reloaded = collection.find_one(:_id => id)
|
152
|
-
if Mongoid.raise_not_found_error
|
153
|
-
raise Errors::DocumentNotFound.new(self.class, id) if reloaded.nil?
|
154
|
-
end
|
155
|
-
@attributes = {}.merge(reloaded || {})
|
156
|
-
changed_attributes.clear
|
157
|
-
apply_defaults
|
158
|
-
tap do
|
159
|
-
reload_relations
|
160
|
-
run_callbacks(:initialize)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
140
|
# Return an array with this +Document+ only in it.
|
165
141
|
#
|
166
142
|
# @example Return the document in an array.
|
@@ -26,6 +26,19 @@ module Mongoid #:nodoc:
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
# Get the id attribute from this hash, whether it's prefixed with an
|
31
|
+
# underscore or is a symbol.
|
32
|
+
#
|
33
|
+
# @example Extract the id.
|
34
|
+
# { :_id => 1 }.extract_id
|
35
|
+
#
|
36
|
+
# @return [ Object ] The value of the id.
|
37
|
+
#
|
38
|
+
# @since 2.3.2
|
39
|
+
def extract_id
|
40
|
+
self["id"] || self["_id"] || self[:id] || self[:_id]
|
41
|
+
end
|
29
42
|
end
|
30
43
|
end
|
31
44
|
end
|
@@ -51,7 +51,12 @@ module Mongoid #:nodoc:
|
|
51
51
|
# @since 2.0.0.rc.7
|
52
52
|
def matcher(document, key, value)
|
53
53
|
if value.is_a?(Hash)
|
54
|
-
MATCHERS[value.keys.first]
|
54
|
+
matcher = MATCHERS[value.keys.first]
|
55
|
+
if matcher
|
56
|
+
matcher.new(extract_attribute(document, key))
|
57
|
+
else
|
58
|
+
Default.new(extract_attribute(document, key))
|
59
|
+
end
|
55
60
|
else
|
56
61
|
case key
|
57
62
|
when "$or" then Matchers::Or.new(value, document)
|
data/lib/mongoid/persistence.rb
CHANGED
@@ -168,7 +168,7 @@ module Mongoid #:nodoc:
|
|
168
168
|
#
|
169
169
|
# @return [ Document ] The newly created document.
|
170
170
|
def create(attributes = {}, options = {}, &block)
|
171
|
-
|
171
|
+
_creating do
|
172
172
|
new(attributes, options, &block).tap { |doc| doc.save }
|
173
173
|
end
|
174
174
|
end
|
@@ -187,7 +187,7 @@ module Mongoid #:nodoc:
|
|
187
187
|
#
|
188
188
|
# @return [ Document ] The newly created document.
|
189
189
|
def create!(attributes = {}, options = {}, &block)
|
190
|
-
|
190
|
+
_creating do
|
191
191
|
new(attributes, options, &block).tap do |doc|
|
192
192
|
fail_validate!(doc) if doc.insert.errors.any?
|
193
193
|
fail_callback!(doc, :create!) if doc.new?
|
@@ -259,25 +259,6 @@ module Mongoid #:nodoc:
|
|
259
259
|
def fail_callback!(document, method)
|
260
260
|
raise Errors::Callback.new(document.class, method)
|
261
261
|
end
|
262
|
-
|
263
|
-
private
|
264
|
-
|
265
|
-
# Execute a block in creating mode.
|
266
|
-
#
|
267
|
-
# @example Execute in creating mode.
|
268
|
-
# creating do
|
269
|
-
# relation.push(doc)
|
270
|
-
# end
|
271
|
-
#
|
272
|
-
# @return [ Object ] The return value of the block.
|
273
|
-
#
|
274
|
-
# @since 2.1.0
|
275
|
-
def creating
|
276
|
-
Threaded.begin_create
|
277
|
-
yield
|
278
|
-
ensure
|
279
|
-
Threaded.exit_create
|
280
|
-
end
|
281
262
|
end
|
282
263
|
end
|
283
264
|
end
|
data/lib/mongoid/railtie.rb
CHANGED
@@ -95,7 +95,14 @@ module Rails #:nodoc:
|
|
95
95
|
# environments.
|
96
96
|
initializer "preload all application models" do |app|
|
97
97
|
config.to_prepare do
|
98
|
-
|
98
|
+
if $rails_rake_task
|
99
|
+
# We previously got rid of this, however in the case where
|
100
|
+
# threadsafe! is enabled we must load all models so things like
|
101
|
+
# creating indexes works properly.
|
102
|
+
::Rails::Mongoid.load_models(app)
|
103
|
+
else
|
104
|
+
::Rails::Mongoid.preload_models(app)
|
105
|
+
end
|
99
106
|
end
|
100
107
|
end
|
101
108
|
|
@@ -22,8 +22,8 @@ module Mongoid # :nodoc:
|
|
22
22
|
# @return [ Proxy ] The relation.
|
23
23
|
#
|
24
24
|
# @since 2.0.0.rc.1
|
25
|
-
def build(name, object, metadata
|
26
|
-
relation = create_relation(object, metadata
|
25
|
+
def build(name, object, metadata)
|
26
|
+
relation = create_relation(object, metadata)
|
27
27
|
set_relation(name, relation)
|
28
28
|
end
|
29
29
|
|
@@ -38,9 +38,9 @@ module Mongoid # :nodoc:
|
|
38
38
|
# @return [ Proxy ] The relation.
|
39
39
|
#
|
40
40
|
# @since 2.0.0.rc.1
|
41
|
-
def create_relation(object, metadata
|
41
|
+
def create_relation(object, metadata)
|
42
42
|
type = @attributes[metadata.inverse_type]
|
43
|
-
target = metadata.builder(
|
43
|
+
target = metadata.builder(self, object).build(type)
|
44
44
|
target ? metadata.relation.new(self, target, metadata) : nil
|
45
45
|
end
|
46
46
|
|
@@ -97,7 +97,9 @@ module Mongoid # :nodoc:
|
|
97
97
|
instance_variable_get(variable)
|
98
98
|
else
|
99
99
|
_building do
|
100
|
-
|
100
|
+
_loading do
|
101
|
+
build(name, attributes[metadata.key], metadata)
|
102
|
+
end
|
101
103
|
end
|
102
104
|
end
|
103
105
|
end
|
@@ -4,36 +4,9 @@ module Mongoid # :nodoc:
|
|
4
4
|
|
5
5
|
# Superclass for all objects that bind relations together.
|
6
6
|
class Binding
|
7
|
-
|
8
|
-
|
9
|
-
# Execute a block in binding mode.
|
10
|
-
#
|
11
|
-
# @example Execute in binding mode.
|
12
|
-
# binding do
|
13
|
-
# relation.push(doc)
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# @return [ Object ] The return value of the block.
|
17
|
-
#
|
18
|
-
# @since 2.1.0
|
19
|
-
def binding
|
20
|
-
Threaded.begin_bind
|
21
|
-
yield
|
22
|
-
ensure
|
23
|
-
Threaded.exit_bind
|
24
|
-
end
|
7
|
+
include Threaded::Lifecycle
|
25
8
|
|
26
|
-
|
27
|
-
#
|
28
|
-
# @example Is the thread in binding mode?
|
29
|
-
# binding.binding?
|
30
|
-
#
|
31
|
-
# @return [ true, false ] If the thread is binding.
|
32
|
-
#
|
33
|
-
# @since 2.1.0
|
34
|
-
def binding?
|
35
|
-
Threaded.binding?
|
36
|
-
end
|
9
|
+
attr_reader :base, :target, :metadata
|
37
10
|
|
38
11
|
# Create the new binding.
|
39
12
|
#
|