mongoid 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +16 -1
- data/lib/mongoid/callbacks.rb +32 -0
- data/lib/mongoid/contextual/mongo.rb +4 -18
- data/lib/mongoid/criteria.rb +58 -15
- data/lib/mongoid/extensions/big_decimal.rb +12 -0
- data/lib/mongoid/extensions/object.rb +12 -0
- data/lib/mongoid/persistence/atomic/inc.rb +16 -1
- data/lib/mongoid/persistence/atomic/operation.rb +15 -1
- data/lib/mongoid/relations/auto_save.rb +11 -6
- data/lib/mongoid/relations/embedded/many.rb +10 -0
- data/lib/mongoid/relations/many.rb +0 -10
- data/lib/mongoid/relations/referenced/many.rb +10 -0
- data/lib/mongoid/version.rb +1 -1
- metadata +7 -7
data/CHANGELOG.md
CHANGED
@@ -3,7 +3,22 @@
|
|
3
3
|
For instructions on upgrading to newer versions, visit
|
4
4
|
[mongoid.org](http://mongoid.org/docs/upgrading.html).
|
5
5
|
|
6
|
-
## 3.0.
|
6
|
+
## 3.0.3
|
7
|
+
|
8
|
+
### Resolved Issues
|
9
|
+
|
10
|
+
* \#2259 Ensure subclassed documents can not be pulled from the identity map
|
11
|
+
via an id of another document in the same collection with a parent or
|
12
|
+
sibeling type.
|
13
|
+
|
14
|
+
* \#2254 $inc operations no longer convert all values to floats.
|
15
|
+
|
16
|
+
* \#2252 Don't fire autosave when before callbacks have terminated.
|
17
|
+
|
18
|
+
* \#2248 Improved the performance of `exists?` on criteria and relations.
|
19
|
+
(Jonathan Hyman)
|
20
|
+
|
21
|
+
## 3.0.2
|
7
22
|
|
8
23
|
### Resolved Issues
|
9
24
|
|
data/lib/mongoid/callbacks.rb
CHANGED
@@ -34,6 +34,8 @@ module Mongoid
|
|
34
34
|
define_model_callbacks :initialize, only: :after
|
35
35
|
define_model_callbacks :build, only: :after
|
36
36
|
define_model_callbacks :create, :destroy, :save, :update, :upsert
|
37
|
+
|
38
|
+
attr_accessor :before_callback_halted
|
37
39
|
end
|
38
40
|
|
39
41
|
# Run only the after callbacks for the specific event.
|
@@ -100,6 +102,21 @@ module Mongoid
|
|
100
102
|
|
101
103
|
private
|
102
104
|
|
105
|
+
# We need to hook into this for autosave, since we don't want it firing if
|
106
|
+
# the before callbacks were halted.
|
107
|
+
#
|
108
|
+
# @api private
|
109
|
+
#
|
110
|
+
# @example Was a before callback halted?
|
111
|
+
# document.before_callback_halted?
|
112
|
+
#
|
113
|
+
# @return [ true, false ] If a before callback was halted.
|
114
|
+
#
|
115
|
+
# @since 3.0.3
|
116
|
+
def before_callback_halted?
|
117
|
+
!!@before_callback_halted
|
118
|
+
end
|
119
|
+
|
103
120
|
# Get all the child embedded documents that are flagged as cascadable.
|
104
121
|
#
|
105
122
|
# @example Get all the cascading children.
|
@@ -169,6 +186,21 @@ module Mongoid
|
|
169
186
|
end
|
170
187
|
end
|
171
188
|
|
189
|
+
# We need to hook into this for autosave, since we don't want it firing if
|
190
|
+
# the before callbacks were halted.
|
191
|
+
#
|
192
|
+
# @api private
|
193
|
+
#
|
194
|
+
# @example Hook into the halt.
|
195
|
+
# document.halted_callback_hook(filter)
|
196
|
+
#
|
197
|
+
# @param [ Symbol ] filter The callback that halted.
|
198
|
+
#
|
199
|
+
# @since 3.0.3
|
200
|
+
def halted_callback_hook(filter)
|
201
|
+
@before_callback_halted = true
|
202
|
+
end
|
203
|
+
|
172
204
|
# Run only the callbacks for the target location (before, after, around)
|
173
205
|
# and kind (save, update, create).
|
174
206
|
#
|
@@ -30,7 +30,7 @@ module Mongoid
|
|
30
30
|
#
|
31
31
|
# @since 3.0.0
|
32
32
|
def blank?
|
33
|
-
|
33
|
+
!exists?
|
34
34
|
end
|
35
35
|
alias :empty? :blank?
|
36
36
|
|
@@ -151,7 +151,8 @@ module Mongoid
|
|
151
151
|
#
|
152
152
|
# @since 3.0.0
|
153
153
|
def exists?
|
154
|
-
count
|
154
|
+
# Don't use count here since Mongo does not use counted b-tree indexes
|
155
|
+
!query.dup.select(_id: 1).limit(1).entries.first.nil?
|
155
156
|
end
|
156
157
|
|
157
158
|
# Run an explain on the criteria.
|
@@ -214,7 +215,7 @@ module Mongoid
|
|
214
215
|
def initialize(criteria)
|
215
216
|
@criteria, @klass, @cache = criteria, criteria.klass, criteria.options[:cache]
|
216
217
|
@collection = klass.collection
|
217
|
-
|
218
|
+
criteria.send(:merge_type_selection)
|
218
219
|
@query = collection.find(criteria.selector)
|
219
220
|
apply_options
|
220
221
|
end
|
@@ -325,21 +326,6 @@ module Mongoid
|
|
325
326
|
|
326
327
|
private
|
327
328
|
|
328
|
-
# For models where inheritance is at play we need to add the type
|
329
|
-
# selection.
|
330
|
-
#
|
331
|
-
# @example Add the type selection.
|
332
|
-
# context.add_type_selection
|
333
|
-
#
|
334
|
-
# @return [ true, false ] If type selection was added.
|
335
|
-
#
|
336
|
-
# @since 3.0.0
|
337
|
-
def add_type_selection
|
338
|
-
if klass.hereditary? && !criteria.selector.keys.include?(:_type)
|
339
|
-
criteria.selector.merge!(_type: { "$in" => klass._types })
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
329
|
# Apply the field limitations.
|
344
330
|
#
|
345
331
|
# @api private
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -178,18 +178,6 @@ module Mongoid
|
|
178
178
|
multi ? result : result.first
|
179
179
|
end
|
180
180
|
|
181
|
-
# Return true if the criteria has some Document or not.
|
182
|
-
#
|
183
|
-
# @example Are there any documents for the criteria?
|
184
|
-
# criteria.exists?
|
185
|
-
#
|
186
|
-
# @return [ true, false ] If documents match.
|
187
|
-
#
|
188
|
-
# @since 1.0.0
|
189
|
-
def exists?
|
190
|
-
context.count > 0
|
191
|
-
end
|
192
|
-
|
193
181
|
# Extract a single id from the provided criteria. Could be in an $and
|
194
182
|
# query or a straight _id query.
|
195
183
|
#
|
@@ -594,12 +582,11 @@ module Mongoid
|
|
594
582
|
#
|
595
583
|
# @since 1.0.0
|
596
584
|
def initialize_copy(other)
|
597
|
-
@selector = other.selector.dup
|
598
|
-
@options = other.options.dup
|
599
585
|
@inclusions = other.inclusions.dup
|
600
586
|
@scoping_options = other.scoping_options
|
601
587
|
@documents = other.documents.dup
|
602
588
|
@context = nil
|
589
|
+
super
|
603
590
|
end
|
604
591
|
|
605
592
|
# Get documents from the database only.
|
@@ -632,9 +619,10 @@ module Mongoid
|
|
632
619
|
# @since 3.0.0
|
633
620
|
def from_identity_map(ids)
|
634
621
|
result = []
|
622
|
+
selection = selector_with_type_selection
|
635
623
|
ids.reject! do |id|
|
636
624
|
doc = IdentityMap.get(klass, id)
|
637
|
-
doc && doc.matches?(
|
625
|
+
doc && doc.matches?(selection) ? result.push(doc) : false
|
638
626
|
end
|
639
627
|
result
|
640
628
|
end
|
@@ -661,6 +649,19 @@ module Mongoid
|
|
661
649
|
end
|
662
650
|
end
|
663
651
|
|
652
|
+
# For models where inheritance is at play we need to add the type
|
653
|
+
# selection.
|
654
|
+
#
|
655
|
+
# @example Add the type selection.
|
656
|
+
# criteria.merge_type_selection
|
657
|
+
#
|
658
|
+
# @return [ true, false ] If type selection was added.
|
659
|
+
#
|
660
|
+
# @since 3.0.3
|
661
|
+
def merge_type_selection
|
662
|
+
selector.merge!(type_selection) if type_selectable?
|
663
|
+
end
|
664
|
+
|
664
665
|
# Convert all the ids to their proper types.
|
665
666
|
#
|
666
667
|
# @api private
|
@@ -688,5 +689,47 @@ module Mongoid
|
|
688
689
|
def raise_invalid
|
689
690
|
raise Errors::InvalidFind.new
|
690
691
|
end
|
692
|
+
|
693
|
+
# Is the criteria type selectable?
|
694
|
+
#
|
695
|
+
# @api private
|
696
|
+
#
|
697
|
+
# @example If the criteria type selectable?
|
698
|
+
# criteria.type_selectable?
|
699
|
+
#
|
700
|
+
# @return [ true, false ] If type selection should be added.
|
701
|
+
#
|
702
|
+
# @since 3.0.3
|
703
|
+
def type_selectable?
|
704
|
+
klass.hereditary? && !selector.keys.include?(:_type)
|
705
|
+
end
|
706
|
+
|
707
|
+
# Get the selector for type selection.
|
708
|
+
#
|
709
|
+
# @api private
|
710
|
+
#
|
711
|
+
# @example Get a type selection hash.
|
712
|
+
# criteria.type_selection
|
713
|
+
#
|
714
|
+
# @return [ Hash ] The type selection.
|
715
|
+
#
|
716
|
+
# @since 3.0.3
|
717
|
+
def type_selection
|
718
|
+
{ _type: { "$in" => klass._types }}
|
719
|
+
end
|
720
|
+
|
721
|
+
# Get a new selector with type selection in it.
|
722
|
+
#
|
723
|
+
# @api private
|
724
|
+
#
|
725
|
+
# @example Get a selector with type selection.
|
726
|
+
# criteria.selector_with_type_selection
|
727
|
+
#
|
728
|
+
# @return [ Hash ] The selector.
|
729
|
+
#
|
730
|
+
# @since 3.0.3
|
731
|
+
def selector_with_type_selection
|
732
|
+
type_selectable? ? selector.merge(type_selection) : selector
|
733
|
+
end
|
691
734
|
end
|
692
735
|
end
|
@@ -3,6 +3,18 @@ module Mongoid
|
|
3
3
|
module Extensions
|
4
4
|
module BigDecimal
|
5
5
|
|
6
|
+
# Convert the big decimal to an $inc-able value.
|
7
|
+
#
|
8
|
+
# @example Convert the big decimal.
|
9
|
+
# bd.__to_inc__
|
10
|
+
#
|
11
|
+
# @return [ Float ] The big decimal as a float.
|
12
|
+
#
|
13
|
+
# @since 3.0.3
|
14
|
+
def __to_inc__
|
15
|
+
to_f
|
16
|
+
end
|
17
|
+
|
6
18
|
# Turn the object from the ruby type we deal with to a Mongo friendly
|
7
19
|
# type.
|
8
20
|
#
|
@@ -52,6 +52,18 @@ module Mongoid
|
|
52
52
|
self
|
53
53
|
end
|
54
54
|
|
55
|
+
# Conversion of an object to an $inc-able value.
|
56
|
+
#
|
57
|
+
# @example Convert the object.
|
58
|
+
# 1.__to_inc__
|
59
|
+
#
|
60
|
+
# @return [ Object ] The object.
|
61
|
+
#
|
62
|
+
# @since 3.0.3
|
63
|
+
def __to_inc__
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
55
67
|
# Do or do not, there is no try. -- Yoda.
|
56
68
|
#
|
57
69
|
# @example Do or do not.
|
@@ -17,13 +17,28 @@ module Mongoid
|
|
17
17
|
# @since 2.0.0
|
18
18
|
def persist
|
19
19
|
prepare do
|
20
|
-
self.value = value.to_f
|
21
20
|
current = document[field] || 0
|
22
21
|
document[field] = current + value
|
23
22
|
execute("$inc")
|
24
23
|
document[field]
|
25
24
|
end
|
26
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# In case we need to cast going to the database.
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
#
|
33
|
+
# @example Cast the value.
|
34
|
+
# operation.cast_value
|
35
|
+
#
|
36
|
+
# @return [ Integer, Float ] The value casted.
|
37
|
+
#
|
38
|
+
# @since 3.0.3
|
39
|
+
def cast_value
|
40
|
+
value.__to_inc__
|
41
|
+
end
|
27
42
|
end
|
28
43
|
end
|
29
44
|
end
|
@@ -47,7 +47,7 @@ module Mongoid
|
|
47
47
|
#
|
48
48
|
# @since 2.0.0
|
49
49
|
def operation(modifier)
|
50
|
-
{ modifier => { path =>
|
50
|
+
{ modifier => { path => cast_value } }
|
51
51
|
end
|
52
52
|
|
53
53
|
# Get the path to the field that is getting atomically updated.
|
@@ -82,6 +82,20 @@ module Mongoid
|
|
82
82
|
|
83
83
|
private
|
84
84
|
|
85
|
+
# In case we need to cast going to the database.
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
#
|
89
|
+
# @example Cast the value.
|
90
|
+
# operation.cast_value
|
91
|
+
#
|
92
|
+
# @return [ Object ] The value.
|
93
|
+
#
|
94
|
+
# @since 3.0.3
|
95
|
+
def cast_value
|
96
|
+
value
|
97
|
+
end
|
98
|
+
|
85
99
|
# Executes the common functionality between operations.
|
86
100
|
#
|
87
101
|
# @api private
|
@@ -61,14 +61,19 @@ module Mongoid
|
|
61
61
|
if metadata.autosave? && autosavable?(metadata)
|
62
62
|
autosaved_relations.push(metadata.name)
|
63
63
|
set_callback :save, :after, unless: :autosaved? do |document|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
# @todo: Durran: Remove with Rails 4 after callback termination.
|
65
|
+
if before_callback_halted?
|
66
|
+
self.before_callback_halted = false
|
67
|
+
else
|
68
|
+
begin_autosave
|
69
|
+
relation = document.send(metadata.name)
|
70
|
+
if relation
|
71
|
+
(relation.do_or_do_not(:in_memory) || Array.wrap(relation)).each do |doc|
|
72
|
+
doc.save
|
73
|
+
end
|
69
74
|
end
|
75
|
+
exit_autosave
|
70
76
|
end
|
71
|
-
exit_autosave
|
72
77
|
end
|
73
78
|
end
|
74
79
|
end
|
@@ -178,6 +178,16 @@ module Mongoid
|
|
178
178
|
remove_all(conditions, :destroy)
|
179
179
|
end
|
180
180
|
|
181
|
+
# Determine if any documents in this relation exist in the database.
|
182
|
+
#
|
183
|
+
# @example Are there persisted documents?
|
184
|
+
# person.posts.exists?
|
185
|
+
#
|
186
|
+
# @return [ true, false ] True is persisted documents exist, false if not.
|
187
|
+
def exists?
|
188
|
+
count > 0
|
189
|
+
end
|
190
|
+
|
181
191
|
# Finds a document in this association through several different
|
182
192
|
# methods.
|
183
193
|
#
|
@@ -72,16 +72,6 @@ module Mongoid
|
|
72
72
|
doc
|
73
73
|
end
|
74
74
|
|
75
|
-
# Determine if any documents in this relation exist in the database.
|
76
|
-
#
|
77
|
-
# @example Are there persisted documents?
|
78
|
-
# person.posts.exists?
|
79
|
-
#
|
80
|
-
# @return [ true, false ] True is persisted documents exist, false if not.
|
81
|
-
def exists?
|
82
|
-
count > 0
|
83
|
-
end
|
84
|
-
|
85
75
|
# Find the first document given the conditions, or creates a new document
|
86
76
|
# with the conditions that were supplied.
|
87
77
|
#
|
@@ -166,6 +166,16 @@ module Mongoid
|
|
166
166
|
target.each { |doc| yield(doc) if block_given? }
|
167
167
|
end
|
168
168
|
|
169
|
+
# Determine if any documents in this relation exist in the database.
|
170
|
+
#
|
171
|
+
# @example Are there persisted documents?
|
172
|
+
# person.posts.exists?
|
173
|
+
#
|
174
|
+
# @return [ true, false ] True is persisted documents exist, false if not.
|
175
|
+
def exists?
|
176
|
+
criteria.exists?
|
177
|
+
end
|
178
|
+
|
169
179
|
# Find the matchind document on the association, either based on id or
|
170
180
|
# conditions.
|
171
181
|
#
|
data/lib/mongoid/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.1
|
53
|
+
version: '1.1'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.1
|
61
|
+
version: '1.1'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: origin
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 1.0
|
69
|
+
version: '1.0'
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.0
|
77
|
+
version: '1.0'
|
78
78
|
description: Mongoid is an ODM (Object Document Mapper) Framework for MongoDB, written
|
79
79
|
in Ruby.
|
80
80
|
email:
|
@@ -354,7 +354,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
354
354
|
version: '0'
|
355
355
|
segments:
|
356
356
|
- 0
|
357
|
-
hash: -
|
357
|
+
hash: -2363016562151284772
|
358
358
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
359
359
|
none: false
|
360
360
|
requirements:
|