mongoid 3.0.19 → 3.0.20

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.
@@ -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