mongoid 2.4.8 → 2.4.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,44 @@
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.10 (branch: 2.4.0-stable)
7
+
8
+ ### Resolved Issues
9
+
10
+ ## 2.4.9
11
+
12
+ ### Resolved Issues
13
+
14
+ * \#1943 Ensure numericality validation works for big decimals.
15
+
16
+ * \#1938 Length validation now works with localized fields.
17
+
18
+ * \#1936 Conflicting pushes with other pushes is now properly handled.
19
+
20
+ * \#1933 `Proxy#extend` should delegate through to the target, where
21
+ extending the proxy itself is now handled through `Proxy#proxy_extend`.
22
+
23
+ * \#1930 Ensure complex criteria are expanded in all where clauses.
24
+ (Hans Hasselberg)
25
+
26
+ * \#1928 Deletion of embedded documents via nested attributes now performs
27
+ a $pull with id match criteria instead of a $pullAll to cover all cases.
28
+ Previously newly added defaults to documents that had already persisted
29
+ could not be deleted in this matter since the doc did not match what was
30
+ in the database.
31
+
32
+ * \#1924/\#1917 Fix pushing to embedded relations with default scopes not
33
+ scoping on the new document. (Hans Hasselberg)
34
+
35
+ * \#1922/\#1919 Dropping collections unmemoizes the internally wrapped
36
+ collection, in order to ensure when defining capped collections that
37
+ they are always recreated as capped. (Hans Hasselberg)
38
+
39
+ * \#1916/\#1913 Uniqueness validation no longer is affected by the default
40
+ scope. (Hans Hasselberg)
41
+
42
+ * \#1778 Ensure foreign keys are always set regardless of binding state.
43
+
6
44
  ## 2.4.8
7
45
 
8
46
  ### Resolved Issues
@@ -61,4 +61,4 @@ en:
61
61
  scope_overwrite:
62
62
  "Cannot create scope :%{scope_name}, because of existing method
63
63
  %{model_name}.%{scope_name}."
64
- blank_on_locale: "can't be blank in %{in_locale}"
64
+ blank_on_locale: "can't be blank in %{location}"
@@ -160,15 +160,18 @@ module Mongoid #:nodoc:
160
160
  #
161
161
  # @since 2.2.0
162
162
  def atomic_pulls
163
- delayed_atomic_pulls.inject({}) do |pulls, (name, docs)|
164
- pulls.tap do |pull|
165
- docs.each do |doc|
166
- (pull[doc.atomic_path] ||= []).push(doc.as_document)
167
- doc.destroyed = true
168
- doc.flagged_for_destroy = false
169
- end
163
+ pulls = {}
164
+ delayed_atomic_pulls.each_pair do |_, docs|
165
+ path = nil
166
+ ids = docs.map do |doc|
167
+ path ||= doc.atomic_path
168
+ doc.destroyed = true
169
+ doc.flagged_for_destroy = false
170
+ doc.id
170
171
  end
172
+ pulls[path] = { "_id" => { "$in" => ids }} and path = nil
171
173
  end
174
+ pulls
172
175
  end
173
176
 
174
177
  # Get all the push attributes that need to occur.
@@ -273,7 +276,7 @@ module Mongoid #:nodoc:
273
276
  mods.push(doc.atomic_pushes)
274
277
  mods.push(doc.atomic_array_pushes)
275
278
  mods.add_to_set(doc.atomic_array_add_to_sets)
276
- mods.pull(doc.atomic_array_pulls)
279
+ mods.pull_all(doc.atomic_array_pulls)
277
280
  end
278
281
  end
279
282
  end
@@ -26,18 +26,33 @@ module Mongoid #:nodoc:
26
26
  end
27
27
  end
28
28
 
29
- # Adds pull modifiers to the modifiers hash.
29
+ # Adds pull all modifiers to the modifiers hash.
30
30
  #
31
- # @example Add pull operations.
32
- # modifiers.pull({ "addresses" => { "street" => "Bond" }})
31
+ # @example Add pull all operations.
32
+ # modifiers.pull_all({ "addresses" => { "street" => "Bond" }})
33
33
  #
34
- # @param [ Hash ] modifications The pull modifiers.
34
+ # @param [ Hash ] modifications The pull all modifiers.
35
35
  #
36
- # @since 2.2.0
36
+ # @since 3.0.0
37
+ def pull_all(modifications)
38
+ modifications.each_pair do |field, value|
39
+ add_operation(pull_alls, field, value)
40
+ pull_fields[field.split(".", 2)[0]] = field
41
+ end
42
+ end
43
+
44
+ # Adds pull all modifiers to the modifiers hash.
45
+ #
46
+ # @example Add pull all operations.
47
+ # modifiers.pull({ "addresses" => { "_id" => { "$in" => [ 1, 2, 3 ]}}})
48
+ #
49
+ # @param [ Hash ] modifications The pull all modifiers.
50
+ #
51
+ # @since 3.0.0
37
52
  def pull(modifications)
38
53
  modifications.each_pair do |field, value|
39
- add_operation(pulls, field, value)
40
- pull_fields << field.split(".", 2)[0]
54
+ pulls[field] = value
55
+ pull_fields[field.split(".", 2)[0]] = field
41
56
  end
42
57
  end
43
58
 
@@ -51,6 +66,7 @@ module Mongoid #:nodoc:
51
66
  # @since 2.1.0
52
67
  def push(modifications)
53
68
  modifications.each_pair do |field, value|
69
+ push_fields[field] = field
54
70
  mods = push_conflict?(field) ? conflicting_pushes : pushes
55
71
  add_operation(mods, field, Array.wrap(value))
56
72
  end
@@ -69,7 +85,7 @@ module Mongoid #:nodoc:
69
85
  next if field == "_id"
70
86
  mods = set_conflict?(field) ? conflicting_sets : sets
71
87
  add_operation(mods, field, value)
72
- set_fields << field.split(".", 2)[0]
88
+ set_fields[field.split(".", 2)[0]] = field
73
89
  end
74
90
  end
75
91
 
@@ -133,7 +149,7 @@ module Mongoid #:nodoc:
133
149
  #
134
150
  # @since 2.2.0
135
151
  def set_conflict?(field)
136
- pull_fields.include?(field.split(".", 2)[0])
152
+ pull_fields.has_key?(field.split(".", 2)[0])
137
153
  end
138
154
 
139
155
  # Is the operation going to be a conflict for a $push?
@@ -148,7 +164,8 @@ module Mongoid #:nodoc:
148
164
  # @since 2.2.0
149
165
  def push_conflict?(field)
150
166
  name = field.split(".", 2)[0]
151
- set_fields.include?(name) || pull_fields.include?(name)
167
+ set_fields.has_key?(name) || pull_fields.has_key?(name) ||
168
+ (push_fields.keys.count { |item| item =~ /#{name}/ } > 1)
152
169
  end
153
170
 
154
171
  # Get the conflicting pull modifications.
@@ -208,7 +225,19 @@ module Mongoid #:nodoc:
208
225
  #
209
226
  # @since 2.2.0
210
227
  def pull_fields
211
- @pull_fields ||= []
228
+ @pull_fields ||= {}
229
+ end
230
+
231
+ # Get the names of the fields that need to be pushed.
232
+ #
233
+ # @example Get the push fields.
234
+ # modifiers.push_fields
235
+ #
236
+ # @return [ Array<String> ] The push fields.
237
+ #
238
+ # @since 2.2.0
239
+ def push_fields
240
+ @push_fields ||= {}
212
241
  end
213
242
 
214
243
  # Get the names of the fields that need to be set.
@@ -220,21 +249,33 @@ module Mongoid #:nodoc:
220
249
  #
221
250
  # @since 2.2.0
222
251
  def set_fields
223
- @set_fields ||= []
252
+ @set_fields ||= {}
224
253
  end
225
254
 
226
255
  # Get the $pullAll operations or intialize a new one.
227
256
  #
228
257
  # @example Get the $pullAll operations.
229
- # modifiers.pulls
258
+ # modifiers.pull_alls
230
259
  #
231
260
  # @return [ Hash ] The $pullAll operations.
232
261
  #
233
- # @since 2.1.0
234
- def pulls
262
+ # @since 3.0.0
263
+ def pull_alls
235
264
  self["$pullAll"] ||= {}
236
265
  end
237
266
 
267
+ # Get the $pull operations or intialize a new one.
268
+ #
269
+ # @example Get the $pull operations.
270
+ # modifiers.pulls
271
+ #
272
+ # @return [ Hash ] The $pull operations.
273
+ #
274
+ # @since 3.0.0
275
+ def pulls
276
+ self["$pull"] ||= {}
277
+ end
278
+
238
279
  # Get the $pushAll operations or intialize a new one.
239
280
  #
240
281
  # @example Get the $pushAll operations.
@@ -149,5 +149,9 @@ module Mongoid #:nodoc
149
149
  master(options).update(selector, document, options)
150
150
  end
151
151
  end
152
+
153
+ def drop(*args)
154
+ @master = nil if master.drop
155
+ end
152
156
  end
153
157
  end
@@ -16,12 +16,13 @@ module Mongoid #:nodoc:
16
16
  # @since 1.0.0
17
17
  def expand_complex_criteria
18
18
  {}.tap do |hsh|
19
- each_pair do |k,v|
19
+ each_pair do |k, v|
20
20
  if k.respond_to?(:key) && k.respond_to?(:to_mongo_query)
21
21
  hsh[k.key] ||= {}
22
22
  v = v.expand_complex_criteria if v.is_a?(::Hash)
23
23
  hsh[k.key].merge!(k.to_mongo_query(v))
24
24
  else
25
+ v.map!{|e| e.is_a?(::Hash) ? e.expand_complex_criteria : e } if v.is_a?(::Array)
25
26
  hsh[k] = v
26
27
  end
27
28
  end
@@ -19,7 +19,13 @@ module Mongoid #:nodoc:
19
19
  #
20
20
  # @since 2.1.0
21
21
  def deserialize(object)
22
- object ? ::BigDecimal.new(object) : object
22
+ return object unless object
23
+ begin
24
+ Float(object)
25
+ ::BigDecimal.new(object)
26
+ rescue ArgumentError, TypeError
27
+ object
28
+ end
23
29
  end
24
30
 
25
31
  # Special case to serialize the object.
@@ -15,8 +15,8 @@ module Mongoid #:nodoc:
15
15
  # @return [ true, false ] If the values match.
16
16
  def matches?(value)
17
17
  attribute_array = Array.wrap(@attribute)
18
- value.values.first.all? do |e|
19
- if e.is_a?(Regexp)
18
+ value.values.first.all? do |e|
19
+ if e.is_a?(Regexp)
20
20
  attribute_array.any? { |_attribute| _attribute =~ e }
21
21
  else
22
22
  attribute_array.include?(e)
@@ -15,8 +15,8 @@ module Mongoid #:nodoc:
15
15
  # @return [ true, false ] If a value exists.
16
16
  def matches?(value)
17
17
  attribute_array = Array.wrap(@attribute)
18
- value.values.first.any? do |e|
19
- if e.is_a?(Regexp)
18
+ value.values.first.any? do |e|
19
+ if e.is_a?(Regexp)
20
20
  attribute_array.any? { |_attribute| _attribute =~ e }
21
21
  else
22
22
  attribute_array.include?(e)
@@ -19,13 +19,13 @@ module Mongoid # :nodoc:
19
19
  #
20
20
  # @since 2.0.0.rc.1
21
21
  def bind
22
+ base.you_must(metadata.foreign_key_setter, target.id)
23
+ if metadata.inverse_type
24
+ base.you_must(metadata.inverse_type_setter, target.class.model_name)
25
+ end
22
26
  unless _binding?
23
27
  _binding do
24
28
  inverse = metadata.inverse(target)
25
- base.you_must(metadata.foreign_key_setter, target.id)
26
- if metadata.inverse_type
27
- base.you_must(metadata.inverse_type_setter, target.class.model_name)
28
- end
29
29
  if inverse
30
30
  if set_base_metadata
31
31
  if base.referenced_many?
@@ -49,13 +49,13 @@ module Mongoid # :nodoc:
49
49
  #
50
50
  # @since 2.0.0.rc.1
51
51
  def unbind
52
+ base.you_must(metadata.foreign_key_setter, nil)
53
+ if metadata.inverse_type
54
+ base.you_must(metadata.inverse_type_setter, nil)
55
+ end
52
56
  unless _binding?
53
57
  _binding do
54
58
  inverse = metadata.inverse(target)
55
- base.you_must(metadata.foreign_key_setter, nil)
56
- if metadata.inverse_type
57
- base.you_must(metadata.inverse_type_setter, nil)
58
- end
59
59
  if inverse
60
60
  set_base_metadata
61
61
  if base.referenced_many?
@@ -17,12 +17,12 @@ module Mongoid # :nodoc:
17
17
  #
18
18
  # @since 2.0.0.rc.1
19
19
  def bind_one(doc)
20
+ doc.you_must(metadata.foreign_key_setter, base.id)
21
+ if metadata.type
22
+ doc.you_must(metadata.type_setter, base.class.model_name)
23
+ end
20
24
  unless _binding?
21
25
  _binding do
22
- doc.you_must(metadata.foreign_key_setter, base.id)
23
- if metadata.type
24
- doc.you_must(metadata.type_setter, base.class.model_name)
25
- end
26
26
  doc.send(metadata.inverse_setter, base)
27
27
  end
28
28
  end
@@ -37,12 +37,12 @@ module Mongoid # :nodoc:
37
37
  #
38
38
  # @since 2.0.0.rc.1
39
39
  def unbind_one(doc)
40
+ doc.you_must(metadata.foreign_key_setter, nil)
41
+ if metadata.type
42
+ doc.you_must(metadata.type_setter, nil)
43
+ end
40
44
  unless _binding?
41
45
  _binding do
42
- doc.you_must(metadata.foreign_key_setter, nil)
43
- if metadata.type
44
- doc.you_must(metadata.type_setter, nil)
45
- end
46
46
  doc.send(metadata.inverse_setter, nil)
47
47
  end
48
48
  end
@@ -19,13 +19,13 @@ module Mongoid # :nodoc:
19
19
  #
20
20
  # @since 2.0.0.rc.1
21
21
  def bind
22
+ target.you_must(metadata.foreign_key_setter, base.id)
23
+ if metadata.type
24
+ target.you_must(metadata.type_setter, base.class.model_name)
25
+ end
22
26
  unless _binding?
23
27
  _binding do
24
- target.you_must(metadata.foreign_key_setter, base.id)
25
28
  target.send(metadata.inverse_setter, base)
26
- if metadata.type
27
- target.you_must(metadata.type_setter, base.class.model_name)
28
- end
29
29
  end
30
30
  end
31
31
  end
@@ -40,13 +40,13 @@ module Mongoid # :nodoc:
40
40
  #
41
41
  # @since 2.0.0.rc.1
42
42
  def unbind
43
+ target.you_must(metadata.foreign_key_setter, nil)
44
+ if metadata.type
45
+ target.you_must(metadata.type_setter, nil)
46
+ end
43
47
  unless _binding?
44
48
  _binding do
45
- target.you_must(metadata.foreign_key_setter, nil)
46
49
  target.send(metadata.inverse_setter, nil)
47
- if metadata.type
48
- target.you_must(metadata.type_setter, nil)
49
- end
50
50
  end
51
51
  end
52
52
  end
@@ -300,7 +300,7 @@ module Mongoid # :nodoc:
300
300
  tap do |proxy|
301
301
  if replacement.blank?
302
302
  if _assigning? && !proxy.empty?
303
- base.atomic_unsets.push(proxy.first.atomic_path)
303
+ base.atomic_unsets.push(_unscoped.first.atomic_path)
304
304
  end
305
305
  proxy.clear
306
306
  else
@@ -318,7 +318,7 @@ module Mongoid # :nodoc:
318
318
  doc.save if base.persisted? && !_assigning?
319
319
  end
320
320
  if _assigning?
321
- name = proxy.first.atomic_path
321
+ name = _unscoped.first.atomic_path
322
322
  base.delayed_atomic_sets[name] = proxy.as_document
323
323
  end
324
324
  end
@@ -353,10 +353,10 @@ module Mongoid # :nodoc:
353
353
  #
354
354
  # @since 2.0.0.rc.1
355
355
  def append(document)
356
- target.push(document)
356
+ target.push(*scope([document]))
357
357
  _unscoped.push(document)
358
358
  integrate(document)
359
- document._index = target.size - 1
359
+ document._index = _unscoped.size - 1
360
360
  end
361
361
 
362
362
  # Instantiate the binding associated with this relation.
@@ -5,14 +5,16 @@ module Mongoid # :nodoc:
5
5
  # This class is the superclass for all relation proxy objects, and contains
6
6
  # common behaviour for all of them.
7
7
  class Proxy
8
- include Threaded::Lifecycle
8
+ alias :extend_proxy :extend
9
9
 
10
10
  # We undefine most methods to get them sent through to the target.
11
11
  instance_methods.each do |method|
12
12
  undef_method(method) unless
13
- method =~ /(^__|^send$|^object_id$|^extend$|^respond_to\?$|^tap$)/
13
+ method =~ /(^__|^send|^object_id|^respond_to|^tap|extend_proxy)/
14
14
  end
15
15
 
16
+ include Threaded::Lifecycle
17
+
16
18
  attr_accessor :base, :loaded, :metadata, :target
17
19
 
18
20
  # Backwards compatibility with Mongoid beta releases.
@@ -34,7 +36,7 @@ module Mongoid # :nodoc:
34
36
  def init(base, target, metadata)
35
37
  @base, @target, @metadata = base, target, metadata
36
38
  yield(self) if block_given?
37
- extend metadata.extension if metadata.extension?
39
+ extend_proxy(metadata.extension) if metadata.extension?
38
40
  end
39
41
 
40
42
  # The default substitutable object for a relation proxy is the clone of
@@ -1,8 +1,10 @@
1
1
  # encoding: utf-8
2
+ require "mongoid/validations/localizable"
2
3
  require "mongoid/validations/associated"
3
4
  require "mongoid/validations/format"
4
- require "mongoid/validations/uniqueness"
5
+ require "mongoid/validations/length"
5
6
  require "mongoid/validations/presence"
7
+ require "mongoid/validations/uniqueness"
6
8
 
7
9
  module Mongoid #:nodoc:
8
10
 
@@ -2,7 +2,7 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Validations #:nodoc:
4
4
 
5
- # Validates that the specified attributes do or do not match a certain
5
+ # Validates that the specified attributes do or do not match a certain
6
6
  # regular expression.
7
7
  #
8
8
  # @example Set up the format validator.
@@ -14,27 +14,7 @@ module Mongoid #:nodoc:
14
14
  # validates_format_of :website, :with => URI.regexp
15
15
  # end
16
16
  class FormatValidator < ActiveModel::Validations::FormatValidator
17
-
18
- # Validates each for format.
19
- #
20
- # @example Validate format.
21
- # validator.validate_each(model, :name, "value")
22
- #
23
- # @param [ Document ] document The document.
24
- # @param [ Symbol, String ] attribute The attribute to validate.
25
- # @param [ Object ] value The attribute value.
26
- #
27
- # @since 2.4.2
28
- def validate_each(document, attribute, value)
29
- field = document.fields[attribute.to_s]
30
- if field && field.localized? && !value.blank?
31
- value.each_pair do |_locale, _value|
32
- super(document, attribute, _value)
33
- end
34
- else
35
- super
36
- end
37
- end
17
+ include Localizable
38
18
  end
39
19
  end
40
20
  end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Validations
4
+
5
+ # Validates that the specified attributes do or do not match a certain
6
+ # length.
7
+ #
8
+ # @example Set up the length validator.
9
+ #
10
+ # class Person
11
+ # include Mongoid::Document
12
+ # field :website
13
+ #
14
+ # validates_length_of :website, in: 1..10
15
+ # end
16
+ class LengthValidator < ActiveModel::Validations::LengthValidator
17
+ include Localizable
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Validations
4
+
5
+ # Adds localization support to validations.
6
+ module Localizable
7
+
8
+ # Validates each for localized fields.
9
+ #
10
+ # @example Validate localized fields.
11
+ # validator.validate_each(model, :name, "value")
12
+ #
13
+ # @param [ Document ] document The document.
14
+ # @param [ Symbol, String ] attribute The attribute to validate.
15
+ # @param [ Object ] value The attribute value.
16
+ #
17
+ # @since 2.4.2
18
+ def validate_each(document, attribute, value)
19
+ field = document.fields[attribute.to_s]
20
+ if field.try(:localized?) && !value.blank?
21
+ value.values.each do |_value|
22
+ super(document, attribute, _value)
23
+ end
24
+ else
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -27,9 +27,9 @@ module Mongoid #:nodoc:
27
27
  # @since 2.4.0
28
28
  def validate_each(document, attribute, value)
29
29
  field = document.fields[attribute.to_s]
30
- if field && field.localized? && !value.blank?
30
+ if field.try(:localized?) && !value.blank?
31
31
  value.each_pair do |locale, value|
32
- document.errors.add(attribute, :blank_on_locale, options.merge(:in_locale => locale)) if value.blank?
32
+ document.errors.add(attribute, :blank_on_locale, options.merge(:location => locale)) if value.blank?
33
33
  end
34
34
  else
35
35
  document.errors.add(attribute, :blank, options) if value.blank?
@@ -56,7 +56,7 @@ module Mongoid #:nodoc:
56
56
  )
57
57
  end
58
58
  else
59
- criteria = klass.where(criterion(document, attrib, val))
59
+ criteria = klass.unscoped.where(criterion(document, attrib, val))
60
60
  criteria = scope(criteria, document, attrib)
61
61
  if criteria.exists?
62
62
  document.errors.add(
@@ -146,7 +146,7 @@ module Mongoid #:nodoc:
146
146
  !document._parent || document.embedded_one?
147
147
  end
148
148
 
149
- # Scope reference has changed?
149
+ # Scope reference has changed?
150
150
  #
151
151
  # @example Has scope reference changed?
152
152
  # validator.scope_value_changed?(doc)
@@ -155,7 +155,7 @@ module Mongoid #:nodoc:
155
155
  #
156
156
  # @return [ true, false ] If the scope reference has changed.
157
157
  #
158
- # @since
158
+ # @since
159
159
  def scope_value_changed?(document)
160
160
  Array.wrap(options[:scope]).any? do |item|
161
161
  document.send("attribute_changed?", item.to_s)
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
- VERSION = "2.4.8"
3
+ VERSION = "2.4.9"
4
4
  end
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.8
4
+ version: 2.4.9
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-04-10 00:00:00.000000000 Z
12
+ date: 2012-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -425,6 +425,8 @@ files:
425
425
  - lib/mongoid/timestamps.rb
426
426
  - lib/mongoid/validations/associated.rb
427
427
  - lib/mongoid/validations/format.rb
428
+ - lib/mongoid/validations/length.rb
429
+ - lib/mongoid/validations/localizable.rb
428
430
  - lib/mongoid/validations/presence.rb
429
431
  - lib/mongoid/validations/uniqueness.rb
430
432
  - lib/mongoid/validations.rb
@@ -459,7 +461,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
459
461
  version: '0'
460
462
  segments:
461
463
  - 0
462
- hash: 2935457969941610047
464
+ hash: 3721994237204070315
463
465
  required_rubygems_version: !ruby/object:Gem::Requirement
464
466
  none: false
465
467
  requirements: