mongoid 3.0.19 → 3.0.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,17 +3,44 @@
3
3
  For instructions on upgrading to newer versions, visit
4
4
  [mongoid.org](http://mongoid.org/en/mongoid/docs/upgrading.html).
5
5
 
6
+ ## 3.0.20
7
+
8
+ ### Resolved Issues
9
+
10
+ * \#2774 Ensure validations macros for uniqueness, presence, and associated
11
+ are also available at the instance level.
12
+
13
+ * \#2772 Localized fields are now properly handled when cloning a document.
14
+
15
+ * \#2758 `Mongoid.create_indexes` does not fail when cannot constantize class.
16
+ (Arthur Neves)
17
+
18
+ * \#2743 Persistence options are no longer cleared when loading revisions.
19
+ (Arthur Neves)
20
+
21
+ * \#2741 Fix time mongoization usec rounding errors on MRI and JRuby.
22
+
23
+ * \#2740 Support integer keys in hash fields when using `read_attribute` with
24
+ dot notation.
25
+
26
+ * \#2739 Ensure integer deserialization properly casts to integers.
27
+
28
+ * \#2733 Many to many relations with `inverse_of: nil` do not persist the
29
+ inverse relation on `<<` or `push` if the document is already persisted.
30
+
31
+ * \#2705 Fixed logic around when children can be added to the cascading
32
+ callbacks list.
33
+
6
34
  ## 3.0.19
7
35
 
36
+ ### Resolved Issues
37
+
8
38
  * Released to revert the changes in \#2703.
9
39
 
10
40
  ## 3.0.18
11
41
 
12
42
  ### Resolved Issues
13
43
 
14
- * \#2703 Validations on associated documents on fire if the document is
15
- changed. (Regression)
16
-
17
44
  * \#2707 Calling `find_or_create_by` or `find_by_initialize_by` off a relation
18
45
  with a chained criteria or scope now properly keeps the relations intact on
19
46
  the new or found document.
@@ -173,7 +173,7 @@ module Mongoid
173
173
  # @since 2.3.0
174
174
  def cascadable_child?(kind, child)
175
175
  return false if kind == :initialize || !child.callback_executable?(kind)
176
- [ :create, :destroy ].include?(kind) || child.changed? || child.new_record?
176
+ child.changed? || child.new_record? || child.flagged_for_destroy?
177
177
  end
178
178
 
179
179
  # Get the name of the callback that the child should fire. This changes
@@ -22,8 +22,30 @@ module Mongoid
22
22
  if attrs.delete("versions")
23
23
  attrs["version"] = 1
24
24
  end
25
+ process_localized_attributes(attrs)
25
26
  self.class.new(attrs, without_protection: true)
26
27
  end
27
28
  alias :dup :clone
29
+
30
+ private
31
+
32
+ # When cloning, if the document has localized fields we need to ensure they
33
+ # are properly processed in the clone.
34
+ #
35
+ # @api private
36
+ #
37
+ # @example Process localized attributes.
38
+ # model.process_localized_attributes(attributes)
39
+ #
40
+ # @param [ Hash ] attrs The attributes.
41
+ #
42
+ # @since 3.0.20
43
+ def process_localized_attributes(attrs)
44
+ localized_fields.keys.each do |name|
45
+ if value = attrs.delete(name)
46
+ attrs["#{name}_translations"] = value
47
+ end
48
+ end
49
+ end
28
50
  end
29
51
  end
@@ -86,7 +86,8 @@ module Mongoid
86
86
  keys = string.split(".")
87
87
  value = self
88
88
  keys.each do |key|
89
- value = value[key]
89
+ nested = value[key] || value[key.to_i]
90
+ value = nested
90
91
  end
91
92
  value
92
93
  end
@@ -57,6 +57,7 @@ module Mongoid
57
57
  nil
58
58
  end
59
59
  end
60
+ alias :demongoize :mongoize
60
61
  end
61
62
  end
62
63
  end
@@ -64,9 +64,10 @@ module Mongoid
64
64
  def mongoize(object)
65
65
  return nil if object.blank?
66
66
  begin
67
- t = object.__mongoize_time__
68
- usec = t.strftime("%9N").to_i / 10**3.0
69
- ::Time.at(t.to_i, usec).utc
67
+ time = object.__mongoize_time__
68
+ return time.utc if time.is_a?(::Time)
69
+ usec = time.sec_fraction * 10**6
70
+ ::Time.at(time.to_i, usec).utc
70
71
  rescue ArgumentError
71
72
  raise Errors::InvalidTime.new(object)
72
73
  end
@@ -12,12 +12,14 @@ module Mongoid
12
12
 
13
13
  included do
14
14
  class_attribute :aliased_fields
15
+ class_attribute :localized_fields
15
16
  class_attribute :fields
16
17
  class_attribute :pre_processed_defaults
17
18
  class_attribute :post_processed_defaults
18
19
 
19
20
  self.aliased_fields = { "id" => "_id" }
20
21
  self.fields = {}
22
+ self.localized_fields = {}
21
23
  self.pre_processed_defaults = []
22
24
  self.post_processed_defaults = []
23
25
 
@@ -350,6 +352,7 @@ module Mongoid
350
352
  if options[:localize]
351
353
  create_translations_getter(name, meth)
352
354
  create_translations_setter(name, meth, field)
355
+ localized_fields[name] = field
353
356
  end
354
357
  end
355
358
 
@@ -99,6 +99,11 @@ module Mongoid
99
99
  true
100
100
  end
101
101
 
102
+ # Returns a string representing the documents's key suitable for use in URLs.
103
+ def to_param
104
+ new_record? ? nil : to_key.join('-')
105
+ end
106
+
102
107
  private
103
108
 
104
109
  # Get the collection to be used for paranoid operations.
@@ -30,7 +30,7 @@ module Mongoid
30
30
  if doc = docs.first
31
31
  append(doc)
32
32
  base.add_to_set(foreign_key, doc.id)
33
- if persistable? || _creating?
33
+ if child_persistable?(doc)
34
34
  doc.save
35
35
  end
36
36
  end
@@ -220,6 +220,23 @@ module Mongoid
220
220
  Bindings::Referenced::ManyToMany.new(base, target, metadata)
221
221
  end
222
222
 
223
+ # Determine if the child document should be persisted.
224
+ #
225
+ # @api private
226
+ #
227
+ # @example Is the child persistable?
228
+ # relation.child_persistable?(doc)
229
+ #
230
+ # @param [ Document ] doc The document.
231
+ #
232
+ # @return [ true, false ] If the document can be persisted.
233
+ #
234
+ # @since 3.0.20
235
+ def child_persistable?(doc)
236
+ (persistable? || _creating?) &&
237
+ !(doc.persisted? && metadata.forced_nil_inverse?)
238
+ end
239
+
223
240
  # Returns the criteria object for the target class with its documents set
224
241
  # to target.
225
242
  #
@@ -444,8 +444,8 @@ module Mongoid
444
444
 
445
445
  def matching_document(location)
446
446
  _loaded.try(:values).try(location) ||
447
- _added[_unloaded.try(location).try(:id)] ||
448
- _unloaded.try(location) ||
447
+ _added[(ul = _unloaded.try(location)).try(:id)] ||
448
+ ul ||
449
449
  _added.values.try(location)
450
450
  end
451
451
  end
@@ -151,7 +151,7 @@ module Mongoid
151
151
  def collection
152
152
  if opts = persistence_options
153
153
  coll = mongo_session.with(opts)[opts[:collection] || collection_name]
154
- clear_persistence_options unless validating_with_query?
154
+ clear_persistence_options unless validating_with_query? || _loading_revision?
155
155
  coll
156
156
  else
157
157
  mongo_session[collection_name]
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ require "mongoid/validations/macros"
2
3
  require "mongoid/validations/localizable"
3
4
  require "mongoid/validations/associated"
4
5
  require "mongoid/validations/format"
@@ -15,6 +16,11 @@ module Mongoid
15
16
  extend ActiveSupport::Concern
16
17
  include ActiveModel::Validations
17
18
 
19
+ included do
20
+ extend Macros
21
+ include Macros
22
+ end
23
+
18
24
  # Begin the associated validation.
19
25
  #
20
26
  # @example Begin validation.
@@ -104,90 +110,19 @@ module Mongoid
104
110
 
105
111
  module ClassMethods
106
112
 
107
- # Validates whether or not an association is valid or not. Will correctly
108
- # handle has one and has many associations.
109
- #
110
- # @example
111
- #
112
- # class Person
113
- # include Mongoid::Document
114
- # embeds_one :name
115
- # embeds_many :addresses
116
- #
117
- # validates_associated :name, :addresses
118
- # end
119
- #
120
- # @param [ Array ] *args The arguments to pass to the validator.
121
- def validates_associated(*args)
122
- validates_with(AssociatedValidator, _merge_attributes(args))
123
- end
124
-
125
- # Validates whether or not a field is unique against the documents in the
126
- # database.
127
- #
128
- # @example
129
- #
130
- # class Person
131
- # include Mongoid::Document
132
- # field :title
133
- #
134
- # validates_uniqueness_of :title
135
- # end
136
- #
137
- # @param [ Array ] *args The arguments to pass to the validator.
138
- def validates_uniqueness_of(*args)
139
- validates_with(UniquenessValidator, _merge_attributes(args))
140
- end
141
-
142
- # Validates the format of a field.
143
- #
144
- # @example
145
- # class Person
146
- # include Mongoid::Document
147
- # field :title
148
- #
149
- # validates_format_of :title, with: /^[a-z0-9 \-_]*$/i
150
- # end
151
- #
152
- # @param [ Array ] args The names of the fields to validate.
153
- #
154
- # @since 2.4.0
155
- def validates_format_of(*args)
156
- validates_with(Mongoid::Validations::FormatValidator, _merge_attributes(args))
157
- end
158
-
159
- # Validates the length of a field.
160
- #
161
- # @example
162
- # class Person
163
- # include Mongoid::Document
164
- # field :title
165
- #
166
- # validates_length_of :title, minimum: 100
167
- # end
168
- #
169
- # @param [ Array ] args The names of the fields to validate.
170
- #
171
- # @since 2.4.0
172
- def validates_length_of(*args)
173
- validates_with(Mongoid::Validations::LengthValidator, _merge_attributes(args))
174
- end
175
-
176
- # Validates whether or not a field is present - meaning nil or empty.
177
- #
178
- # @example
179
- # class Person
180
- # include Mongoid::Document
181
- # field :title
113
+ # Adds an associated validator for the relation if the validate option
114
+ # was not provided or set to true.
182
115
  #
183
- # validates_presence_of :title
184
- # end
116
+ # @example Set up validation.
117
+ # Person.validates_relation(metadata)
185
118
  #
186
- # @param [ Array ] args The names of the fields to validate.
119
+ # @param [ Metadata ] metadata The relation metadata.
187
120
  #
188
- # @since 2.4.0
189
- def validates_presence_of(*args)
190
- validates_with(PresenceValidator, _merge_attributes(args))
121
+ # @since 2.0.0.rc.1
122
+ def validates_relation(metadata)
123
+ if metadata.validate?
124
+ validates_associated(metadata.name)
125
+ end
191
126
  end
192
127
 
193
128
  # Add validation with the supplied validators forthe provided fields
@@ -215,23 +150,6 @@ module Mongoid
215
150
  super
216
151
  end
217
152
 
218
- private
219
-
220
- # Adds an associated validator for the relation if the validate option
221
- # was not provided or set to true.
222
- #
223
- # @example Set up validation.
224
- # Person.validates_relation(metadata)
225
- #
226
- # @param [ Metadata ] metadata The relation metadata.
227
- #
228
- # @since 2.0.0.rc.1
229
- def validates_relation(metadata)
230
- if metadata.validate?
231
- validates_associated(metadata.name)
232
- end
233
- end
234
-
235
153
  # Are we currently performing a validation that has a query?
236
154
  #
237
155
  # @example Are we validating with a query?
@@ -0,0 +1,93 @@
1
+ module Mongoid
2
+ module Validations
3
+ module Macros
4
+ extend ActiveSupport::Concern
5
+
6
+ # Validates whether or not an association is valid or not. Will correctly
7
+ # handle has one and has many associations.
8
+ #
9
+ # @example
10
+ #
11
+ # class Person
12
+ # include Mongoid::Document
13
+ # embeds_one :name
14
+ # embeds_many :addresses
15
+ #
16
+ # validates_associated :name, :addresses
17
+ # end
18
+ #
19
+ # @param [ Array ] *args The arguments to pass to the validator.
20
+ def validates_associated(*args)
21
+ validates_with(AssociatedValidator, _merge_attributes(args))
22
+ end
23
+
24
+ # Validates whether or not a field is unique against the documents in the
25
+ # database.
26
+ #
27
+ # @example
28
+ #
29
+ # class Person
30
+ # include Mongoid::Document
31
+ # field :title
32
+ #
33
+ # validates_uniqueness_of :title
34
+ # end
35
+ #
36
+ # @param [ Array ] *args The arguments to pass to the validator.
37
+ def validates_uniqueness_of(*args)
38
+ validates_with(UniquenessValidator, _merge_attributes(args))
39
+ end
40
+
41
+ # Validates the format of a field.
42
+ #
43
+ # @example
44
+ # class Person
45
+ # include Mongoid::Document
46
+ # field :title
47
+ #
48
+ # validates_format_of :title, with: /^[a-z0-9 \-_]*$/i
49
+ # end
50
+ #
51
+ # @param [ Array ] args The names of the fields to validate.
52
+ #
53
+ # @since 2.4.0
54
+ def validates_format_of(*args)
55
+ validates_with(Mongoid::Validations::FormatValidator, _merge_attributes(args))
56
+ end
57
+
58
+ # Validates the length of a field.
59
+ #
60
+ # @example
61
+ # class Person
62
+ # include Mongoid::Document
63
+ # field :title
64
+ #
65
+ # validates_length_of :title, minimum: 100
66
+ # end
67
+ #
68
+ # @param [ Array ] args The names of the fields to validate.
69
+ #
70
+ # @since 2.4.0
71
+ def validates_length_of(*args)
72
+ validates_with(Mongoid::Validations::LengthValidator, _merge_attributes(args))
73
+ end
74
+
75
+ # Validates whether or not a field is present - meaning nil or empty.
76
+ #
77
+ # @example
78
+ # class Person
79
+ # include Mongoid::Document
80
+ # field :title
81
+ #
82
+ # validates_presence_of :title
83
+ # end
84
+ #
85
+ # @param [ Array ] args The names of the fields to validate.
86
+ #
87
+ # @since 2.4.0
88
+ def validates_presence_of(*args)
89
+ validates_with(PresenceValidator, _merge_attributes(args))
90
+ end
91
+ end
92
+ end
93
+ end
@@ -17,6 +17,7 @@ module Mongoid
17
17
  #
18
18
  # @since 3.0.2
19
19
  def with_query(document)
20
+ klass = document.class
20
21
  begin
21
22
  Threaded.begin("#{klass.name}-validate-with-query")
22
23
  yield
@@ -16,20 +16,6 @@ module Mongoid
16
16
  class UniquenessValidator < ActiveModel::EachValidator
17
17
  include Queryable
18
18
 
19
- attr_reader :klass
20
-
21
- # Unfortunately, we have to tie Uniqueness validators to a class.
22
- #
23
- # @example Setup the validator.
24
- # UniquenessValidator.new.setup(Person)
25
- #
26
- # @param [ Class ] klass The class getting validated.
27
- #
28
- # @since 1.0.0
29
- def setup(klass)
30
- @klass = klass
31
- end
32
-
33
19
  # Validate the document for uniqueness violations.
34
20
  #
35
21
  # @example Validate the document.
@@ -266,7 +252,7 @@ module Mongoid
266
252
  #
267
253
  # @since 2.4.10
268
254
  def validate_root(document, attribute, value)
269
- criteria = create_criteria(klass, document, attribute, value)
255
+ criteria = create_criteria(document.class, document, attribute, value)
270
256
  if criteria.with(consistency: :strong).exists?
271
257
  add_error(document, attribute, value)
272
258
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid
3
- VERSION = "3.0.19"
3
+ VERSION = "3.0.20"
4
4
  end
@@ -146,9 +146,9 @@ module Rails
146
146
  klass = name.constantize
147
147
  rescue NameError, LoadError
148
148
  logger.info("MONGOID: Attempted to constantize #{name}, trying without namespacing.")
149
- klass = parts.last.constantize
149
+ klass = parts.last.constantize rescue nil
150
150
  end
151
- klass if klass.ancestors.include?(::Mongoid::Document)
151
+ klass if klass && klass.ancestors.include?(::Mongoid::Document)
152
152
  end
153
153
  end
154
154
  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: 3.0.19
4
+ version: 3.0.20
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: 2013-01-23 00:00:00.000000000 Z
12
+ date: 2013-02-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -321,6 +321,7 @@ files:
321
321
  - lib/mongoid/validations/format.rb
322
322
  - lib/mongoid/validations/length.rb
323
323
  - lib/mongoid/validations/localizable.rb
324
+ - lib/mongoid/validations/macros.rb
324
325
  - lib/mongoid/validations/presence.rb
325
326
  - lib/mongoid/validations/queryable.rb
326
327
  - lib/mongoid/validations/uniqueness.rb