mongoid 2.4.9 → 2.4.10
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 +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.
|