mongoid 2.4.9 → 2.4.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +28 -1
- data/lib/mongoid/atomic.rb +3 -0
- data/lib/mongoid/contexts/mongo.rb +8 -6
- data/lib/mongoid/factory.rb +3 -3
- data/lib/mongoid/identity_map.rb +15 -0
- data/lib/mongoid/multi_database.rb +5 -0
- data/lib/mongoid/relations/cascading/delete.rb +11 -1
- data/lib/mongoid/relations/embedded/many.rb +15 -3
- data/lib/mongoid/relations/one.rb +12 -0
- data/lib/mongoid/relations/referenced/many.rb +7 -1
- data/lib/mongoid/validations.rb +34 -0
- data/lib/mongoid/validations/uniqueness.rb +99 -19
- data/lib/mongoid/version.rb +1 -1
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -3,10 +3,37 @@
|
|
3
3
|
For instructions on upgrading to newer versions, visit
|
4
4
|
[mongoid.org](http://mongoid.org/docs/upgrading.html).
|
5
5
|
|
6
|
-
## 2.4.
|
6
|
+
## 2.4.11 (branch: 2.4.0-stable)
|
7
7
|
|
8
8
|
### Resolved Issues
|
9
9
|
|
10
|
+
## 2.4.10
|
11
|
+
|
12
|
+
### Resolved Issues
|
13
|
+
|
14
|
+
* \#2003 Don't fail on document generation when an embedded document was
|
15
|
+
stored as nil in the database.
|
16
|
+
|
17
|
+
* \#1997 Don't delete paranoid embedded docs via nested attributes when
|
18
|
+
a before_destroy callback returns false.
|
19
|
+
|
20
|
+
* \#1994 `dependent: :delete` only hits the database once now for one to
|
21
|
+
many and many to many relations instead of once for each document.
|
22
|
+
|
23
|
+
* \#1987 Don't double-insert documents into identity map when eager loading
|
24
|
+
twice inside the unit of work.
|
25
|
+
|
26
|
+
* \#1976 Don't execute eager load queries when base query is empty.
|
27
|
+
|
28
|
+
* \#1953 Uniqueness validation now works on localized fields.
|
29
|
+
|
30
|
+
* \#1936 Allow setting n levels deep embedded documents atomically without
|
31
|
+
conflicting mods when not using nested attributes or documents themselves
|
32
|
+
in an update call from the parent.
|
33
|
+
|
34
|
+
* \#1957/\#1954 Ensure database name is set with inheritance.
|
35
|
+
(Hans Hasselberg)
|
36
|
+
|
10
37
|
## 2.4.9
|
11
38
|
|
12
39
|
### Resolved Issues
|
data/lib/mongoid/atomic.rb
CHANGED
@@ -252,6 +252,9 @@ module Mongoid #:nodoc:
|
|
252
252
|
# @example Get the atomic paths.
|
253
253
|
# document.atomic_paths
|
254
254
|
#
|
255
|
+
# @todo: Durran: Should probably raise error for embedded docs w/o
|
256
|
+
# metadata.
|
257
|
+
#
|
255
258
|
# @return [ Object ] The associated path.
|
256
259
|
#
|
257
260
|
# @since 2.1.0
|
@@ -144,13 +144,15 @@ module Mongoid #:nodoc:
|
|
144
144
|
#
|
145
145
|
# @since 2.4.1
|
146
146
|
def eager_load(docs)
|
147
|
-
parent_ids = docs.map(&:id)
|
148
147
|
criteria.inclusions.reject! do |metadata|
|
149
|
-
|
150
|
-
|
151
|
-
metadata.
|
152
|
-
|
153
|
-
|
148
|
+
unless docs.empty?
|
149
|
+
parent_ids = docs.map(&:id)
|
150
|
+
if metadata.macro == :referenced_in
|
151
|
+
child_ids = load_ids(metadata.foreign_key)
|
152
|
+
metadata.eager_load(child_ids)
|
153
|
+
else
|
154
|
+
metadata.eager_load(parent_ids)
|
155
|
+
end
|
154
156
|
end
|
155
157
|
end
|
156
158
|
end
|
data/lib/mongoid/factory.rb
CHANGED
@@ -15,7 +15,7 @@ module Mongoid #:nodoc:
|
|
15
15
|
# @param [ Hash ] optiosn The mass assignment scoping options.
|
16
16
|
#
|
17
17
|
# @return [ Document ] The instantiated document.
|
18
|
-
def build(klass, attributes =
|
18
|
+
def build(klass, attributes = nil, options = {})
|
19
19
|
type = (attributes || {})["_type"]
|
20
20
|
if type && klass._types.include?(type)
|
21
21
|
type.constantize.new(attributes, options)
|
@@ -34,8 +34,8 @@ module Mongoid #:nodoc:
|
|
34
34
|
# @param [ Hash ] attributes The document attributes.
|
35
35
|
#
|
36
36
|
# @return [ Document ] The instantiated document.
|
37
|
-
def from_db(klass, attributes =
|
38
|
-
type = attributes["_type"]
|
37
|
+
def from_db(klass, attributes = nil)
|
38
|
+
type = (attributes || {})["_type"]
|
39
39
|
if type.blank?
|
40
40
|
klass.instantiate(attributes)
|
41
41
|
else
|
data/lib/mongoid/identity_map.rb
CHANGED
@@ -4,6 +4,21 @@ module Mongoid #:nodoc:
|
|
4
4
|
# Defines behaviour for the identity map in Mongoid.
|
5
5
|
class IdentityMap < Hash
|
6
6
|
|
7
|
+
# Clear the many documents.
|
8
|
+
#
|
9
|
+
# @example Clear the docs.
|
10
|
+
# identity_map.clear_many(Post, selector)
|
11
|
+
#
|
12
|
+
# @param [ Class ] klass The klass to clear.
|
13
|
+
# @param [ Hash ] selector The selector to identify it.
|
14
|
+
#
|
15
|
+
# @return [ Array<Document> ] The documents.
|
16
|
+
#
|
17
|
+
# @since 2.4.10
|
18
|
+
def clear_many(klass, selector)
|
19
|
+
(documents_for(klass)[selector] ||= []).clear
|
20
|
+
end
|
21
|
+
|
7
22
|
# Get a document from the identity map by its id.
|
8
23
|
#
|
9
24
|
# @example Get the document from the map.
|
@@ -27,8 +27,18 @@ module Mongoid # :nodoc:
|
|
27
27
|
#
|
28
28
|
# @example Perform the cascading delete.
|
29
29
|
# strategy.cascade
|
30
|
+
#
|
31
|
+
# @since 2.0.0
|
30
32
|
def cascade
|
31
|
-
|
33
|
+
if relation
|
34
|
+
if relation.cascades.empty?
|
35
|
+
safety = Threaded.safety_options
|
36
|
+
relation.clear
|
37
|
+
Threaded.safety_options = safety
|
38
|
+
else
|
39
|
+
::Array.wrap(relation).each { |doc| doc.delete }
|
40
|
+
end
|
41
|
+
end
|
32
42
|
end
|
33
43
|
end
|
34
44
|
end
|
@@ -189,8 +189,12 @@ module Mongoid # :nodoc:
|
|
189
189
|
target.delete_one(document).tap do |doc|
|
190
190
|
_unscoped.delete_one(doc)
|
191
191
|
if doc && !_binding?
|
192
|
-
if _assigning?
|
193
|
-
|
192
|
+
if _assigning?
|
193
|
+
if doc.paranoid?
|
194
|
+
doc.destroy(:suppress => true)
|
195
|
+
else
|
196
|
+
base.add_atomic_pull(doc)
|
197
|
+
end
|
194
198
|
else
|
195
199
|
doc.delete(:suppress => true)
|
196
200
|
end
|
@@ -307,7 +311,11 @@ module Mongoid # :nodoc:
|
|
307
311
|
atomically(:$set) do
|
308
312
|
base.delayed_atomic_sets.clear
|
309
313
|
if replacement.first.is_a?(Hash)
|
310
|
-
replacement =
|
314
|
+
replacement = replacement.map do |doc|
|
315
|
+
attributes = { :metadata => metadata, :_parent => base }
|
316
|
+
attributes.merge!(doc)
|
317
|
+
Factory.build(klass, attributes)
|
318
|
+
end
|
311
319
|
end
|
312
320
|
docs = replacement.compact
|
313
321
|
proxy.target = docs
|
@@ -319,6 +327,10 @@ module Mongoid # :nodoc:
|
|
319
327
|
end
|
320
328
|
if _assigning?
|
321
329
|
name = _unscoped.first.atomic_path
|
330
|
+
base._children.each do |child|
|
331
|
+
child.delayed_atomic_sets.clear
|
332
|
+
end
|
333
|
+
base.instance_variable_set(:@_children, nil)
|
322
334
|
base.delayed_atomic_sets[name] = proxy.as_document
|
323
335
|
end
|
324
336
|
end
|
@@ -6,6 +6,18 @@ module Mongoid # :nodoc:
|
|
6
6
|
# behaviour or those proxies.
|
7
7
|
class One < Proxy
|
8
8
|
|
9
|
+
# Clear this relation - same as calling #delete on the document.
|
10
|
+
#
|
11
|
+
# @example Clear the relation.
|
12
|
+
# relation.clear
|
13
|
+
#
|
14
|
+
# @return [ true, false ] If the delete suceeded.
|
15
|
+
#
|
16
|
+
# @since 3.0.0
|
17
|
+
def clear
|
18
|
+
target.delete
|
19
|
+
end
|
20
|
+
|
9
21
|
# Get all the documents in the relation that are loaded into memory.
|
10
22
|
#
|
11
23
|
# @example Get the in memory documents.
|
@@ -563,9 +563,15 @@ module Mongoid #:nodoc:
|
|
563
563
|
#
|
564
564
|
# @since 2.2.0
|
565
565
|
def eager_load(metadata, ids)
|
566
|
+
cleared = false
|
566
567
|
klass, foreign_key = metadata.klass, metadata.foreign_key
|
567
568
|
klass.any_in(foreign_key => ids).each do |doc|
|
568
|
-
|
569
|
+
base_id = doc.send(foreign_key)
|
570
|
+
unless cleared
|
571
|
+
IdentityMap.clear_many(klass, foreign_key => base_id)
|
572
|
+
cleared = true
|
573
|
+
end
|
574
|
+
IdentityMap.set_many(doc, foreign_key => base_id)
|
569
575
|
end
|
570
576
|
end
|
571
577
|
|
data/lib/mongoid/validations.rb
CHANGED
@@ -141,6 +141,40 @@ module Mongoid #:nodoc:
|
|
141
141
|
validates_with(UniquenessValidator, _merge_attributes(args))
|
142
142
|
end
|
143
143
|
|
144
|
+
# Validates the format of a field.
|
145
|
+
#
|
146
|
+
# @example
|
147
|
+
# class Person
|
148
|
+
# include Mongoid::Document
|
149
|
+
# field :title
|
150
|
+
#
|
151
|
+
# validates_format_of :title, with: /^[a-z0-9 \-_]*$/i
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
# @param [ Array ] args The names of the fields to validate.
|
155
|
+
#
|
156
|
+
# @since 2.4.0
|
157
|
+
def validates_format_of(*args)
|
158
|
+
validates_with(Mongoid::Validations::FormatValidator, _merge_attributes(args))
|
159
|
+
end
|
160
|
+
|
161
|
+
# Validates the length of a field.
|
162
|
+
#
|
163
|
+
# @example
|
164
|
+
# class Person
|
165
|
+
# include Mongoid::Document
|
166
|
+
# field :title
|
167
|
+
#
|
168
|
+
# validates_length_of :title, minimum: 100
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# @param [ Array ] args The names of the fields to validate.
|
172
|
+
#
|
173
|
+
# @since 2.4.0
|
174
|
+
def validates_length_of(*args)
|
175
|
+
validates_with(Mongoid::Validations::LengthValidator, _merge_attributes(args))
|
176
|
+
end
|
177
|
+
|
144
178
|
# Validates whether or not a field is present - meaning nil or empty.
|
145
179
|
#
|
146
180
|
# @example
|
@@ -44,32 +44,36 @@ module Mongoid #:nodoc:
|
|
44
44
|
attrib, val = to_validate(document, attribute, value)
|
45
45
|
return unless validation_required?(document, attrib)
|
46
46
|
if document.embedded?
|
47
|
-
|
48
|
-
relation = document._parent.send(document.metadata.name)
|
49
|
-
criteria = relation.where(criterion(document, attrib, val))
|
50
|
-
criteria = scope(criteria, document, attrib)
|
51
|
-
if criteria.count > 1
|
52
|
-
document.errors.add(
|
53
|
-
attrib,
|
54
|
-
:taken,
|
55
|
-
options.except(:case_sensitive, :scope).merge(:val => val)
|
56
|
-
)
|
57
|
-
end
|
47
|
+
validate_embedded(document, attrib, val)
|
58
48
|
else
|
59
|
-
|
60
|
-
criteria = scope(criteria, document, attrib)
|
61
|
-
if criteria.exists?
|
62
|
-
document.errors.add(
|
63
|
-
attrib, :taken, options.except(:case_sensitive, :scope).merge(:val => val)
|
64
|
-
)
|
65
|
-
end
|
49
|
+
validate_root(document, attrib, val)
|
66
50
|
end
|
67
51
|
end
|
68
52
|
|
69
|
-
|
53
|
+
private
|
54
|
+
|
55
|
+
# Add the error to the document.
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
#
|
59
|
+
# @example Add the error.
|
60
|
+
# validator.add_error(doc, :name, "test")
|
61
|
+
#
|
62
|
+
# @param [ Document ] document The document to validate.
|
63
|
+
# @param [ Symbol ] attribute The name of the attribute.
|
64
|
+
# @param [ Object ] value The value of the object.
|
65
|
+
#
|
66
|
+
# @since 2.4.10
|
67
|
+
def add_error(document, attribute, value)
|
68
|
+
document.errors.add(
|
69
|
+
attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value)
|
70
|
+
)
|
71
|
+
end
|
70
72
|
|
71
73
|
# Should the uniqueness validation be case sensitive?
|
72
74
|
#
|
75
|
+
# @api private
|
76
|
+
#
|
73
77
|
# @example Is the validation case sensitive?
|
74
78
|
# validator.case_sensitive?
|
75
79
|
#
|
@@ -80,8 +84,38 @@ module Mongoid #:nodoc:
|
|
80
84
|
!(options[:case_sensitive] == false)
|
81
85
|
end
|
82
86
|
|
87
|
+
# Create the validation criteria.
|
88
|
+
#
|
89
|
+
# @api private
|
90
|
+
#
|
91
|
+
# @example Create the criteria.
|
92
|
+
# validator.create_criteria(User, user, :name, "syd")
|
93
|
+
#
|
94
|
+
# @param [ Class, Proxy ] base The base to execute the criteria from.
|
95
|
+
# @param [ Document ] document The document to validate.
|
96
|
+
# @param [ Symbol ] attribute The name of the attribute.
|
97
|
+
# @param [ Object ] value The value of the object.
|
98
|
+
#
|
99
|
+
# @return [ Criteria ] The criteria.
|
100
|
+
#
|
101
|
+
# @since 2.4.10
|
102
|
+
def create_criteria(base, document, attribute, value)
|
103
|
+
field = document.fields[attribute.to_s]
|
104
|
+
criteria = base.unscoped
|
105
|
+
if field.try(:localized?)
|
106
|
+
criterion(document, attribute, value).each_pair do |key, value|
|
107
|
+
criteria.selector.store(key, value)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
criteria = criteria.where(criterion(document, attribute, value))
|
111
|
+
end
|
112
|
+
scope(criteria, document, attribute)
|
113
|
+
end
|
114
|
+
|
83
115
|
# Get the default criteria for checking uniqueness.
|
84
116
|
#
|
117
|
+
# @api private
|
118
|
+
#
|
85
119
|
# @example Get the criteria.
|
86
120
|
# validator.criterion(person, :title, "Sir")
|
87
121
|
#
|
@@ -102,6 +136,8 @@ module Mongoid #:nodoc:
|
|
102
136
|
|
103
137
|
# Filter the value based on whether the check is case sensitive or not.
|
104
138
|
#
|
139
|
+
# @api private
|
140
|
+
#
|
105
141
|
# @example Filter the value.
|
106
142
|
# validator.filter("testing")
|
107
143
|
#
|
@@ -116,6 +152,8 @@ module Mongoid #:nodoc:
|
|
116
152
|
|
117
153
|
# Scope the criteria to the scope options provided.
|
118
154
|
#
|
155
|
+
# @api private
|
156
|
+
#
|
119
157
|
# @example Scope the criteria.
|
120
158
|
# validator.scope(criteria, document)
|
121
159
|
#
|
@@ -134,6 +172,8 @@ module Mongoid #:nodoc:
|
|
134
172
|
|
135
173
|
# Should validation be skipped?
|
136
174
|
#
|
175
|
+
# @api private
|
176
|
+
#
|
137
177
|
# @example Should the validation be skipped?
|
138
178
|
# validator.skip_validation?(doc)
|
139
179
|
#
|
@@ -148,6 +188,8 @@ module Mongoid #:nodoc:
|
|
148
188
|
|
149
189
|
# Scope reference has changed?
|
150
190
|
#
|
191
|
+
# @api private
|
192
|
+
#
|
151
193
|
# @example Has scope reference changed?
|
152
194
|
# validator.scope_value_changed?(doc)
|
153
195
|
#
|
@@ -167,6 +209,8 @@ module Mongoid #:nodoc:
|
|
167
209
|
# we need to send the key name and value to the db, not the relation
|
168
210
|
# object.
|
169
211
|
#
|
212
|
+
# @api private
|
213
|
+
#
|
170
214
|
# @example Get the name and key to validate.
|
171
215
|
# validator.to_validate(doc, :parent, Parent.new)
|
172
216
|
#
|
@@ -186,6 +230,42 @@ module Mongoid #:nodoc:
|
|
186
230
|
end
|
187
231
|
end
|
188
232
|
|
233
|
+
# Validate an embedded document.
|
234
|
+
#
|
235
|
+
# @api private
|
236
|
+
#
|
237
|
+
# @example Validate the embedded document.
|
238
|
+
# validator.validate_embedded(doc, :name, "test")
|
239
|
+
#
|
240
|
+
# @param [ Document ] document The document.
|
241
|
+
# @param [ Symbol ] attribute The attribute name.
|
242
|
+
# @param [ Object ] value The value.
|
243
|
+
#
|
244
|
+
# @since 2.4.10
|
245
|
+
def validate_embedded(document, attribute, value)
|
246
|
+
return if skip_validation?(document)
|
247
|
+
relation = document._parent.send(document.metadata.name)
|
248
|
+
criteria = create_criteria(relation, document, attribute, value)
|
249
|
+
add_error(document, attribute, value) if criteria.count > 1
|
250
|
+
end
|
251
|
+
|
252
|
+
# Validate a root document.
|
253
|
+
#
|
254
|
+
# @api private
|
255
|
+
#
|
256
|
+
# @example Validate the root document.
|
257
|
+
# validator.validate_root(doc, :name, "test")
|
258
|
+
#
|
259
|
+
# @param [ Document ] document The document.
|
260
|
+
# @param [ Symbol ] attribute The attribute name.
|
261
|
+
# @param [ Object ] value The value.
|
262
|
+
#
|
263
|
+
# @since 2.4.10
|
264
|
+
def validate_root(document, attribute, value)
|
265
|
+
criteria = create_criteria(klass, document, attribute, value)
|
266
|
+
add_error(document, attribute, value) if criteria.exists?
|
267
|
+
end
|
268
|
+
|
189
269
|
# Are we required to validate the document?
|
190
270
|
#
|
191
271
|
# @example Is validation needed?
|
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: 2.4.
|
4
|
+
version: 2.4.10
|
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-
|
12
|
+
date: 2012-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -461,7 +461,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
461
461
|
version: '0'
|
462
462
|
segments:
|
463
463
|
- 0
|
464
|
-
hash:
|
464
|
+
hash: 2758014138080710719
|
465
465
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
466
466
|
none: false
|
467
467
|
requirements:
|
@@ -470,7 +470,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
470
470
|
version: 1.3.6
|
471
471
|
requirements: []
|
472
472
|
rubyforge_project: mongoid
|
473
|
-
rubygems_version: 1.8.
|
473
|
+
rubygems_version: 1.8.24
|
474
474
|
signing_key:
|
475
475
|
specification_version: 3
|
476
476
|
summary: Elegant Persistance in Ruby for MongoDB.
|