11
11
module ActiveModel
12
12
# == Active \Model \Errors
13
13
#
14
- # Provides a modified +Hash+ that you can include in your object
14
+ # Provides error related functionalities you can include in your object
15
15
# for handling error messages and interacting with Action View helpers.
16
16
#
17
17
# A minimal implementation could be:
@@ -68,7 +68,10 @@ class Errors
68
68
def_delegators :@errors , :count
69
69
70
70
LEGACY_ATTRIBUTES = [ :messages , :details ] . freeze
71
+ private_constant :LEGACY_ATTRIBUTES
71
72
73
+ # The actual array of +Error+ objects
74
+ # This method is aliased to <tt>objects</tt>.
72
75
attr_reader :errors
73
76
alias :objects :errors
74
77
@@ -205,17 +208,37 @@ def [](attribute)
205
208
DeprecationHandlingMessageArray . new ( messages_for ( attribute ) , self , attribute )
206
209
end
207
210
208
- # Iterates through each error key, value pair in the error messages hash.
211
+ def first
212
+ deprecation_index_access_warning ( :first )
213
+ super
214
+ end
215
+
216
+ def last
217
+ deprecation_index_access_warning ( :last )
218
+ super
219
+ end
220
+
221
+ # Iterates through each error object.
222
+ #
223
+ # person.errors.add(:name, :too_short, count: 2)
224
+ # person.errors.each do |error|
225
+ # # Will yield <#ActiveModel::Error attribute=name, type=too_short,
226
+ # options={:count=>3}>
227
+ # end
228
+ #
229
+ # To be backward compatible with past deprecated hash-like behavior,
230
+ # when block accepts two parameters instead of one, it
231
+ # iterates through each error key, value pair in the error messages hash.
209
232
# Yields the attribute and the error for that attribute. If the attribute
210
233
# has more than one error message, yields once for each error message.
211
234
#
212
235
# person.errors.add(:name, :blank, message: "can't be blank")
213
- # person.errors.each do |attribute, error |
236
+ # person.errors.each do |attribute, message |
214
237
# # Will yield :name and "can't be blank"
215
238
# end
216
239
#
217
240
# person.errors.add(:name, :not_specified, message: "must be specified")
218
- # person.errors.each do |attribute, error |
241
+ # person.errors.each do |attribute, message |
219
242
# # Will yield :name and "can't be blank"
220
243
# # then yield :name and "must be specified"
221
244
# end
@@ -249,7 +272,7 @@ def each(&block)
249
272
# person.errors.messages # => {:name=>["cannot be nil", "must be specified"]}
250
273
# person.errors.values # => [["cannot be nil", "must be specified"]]
251
274
def values
252
- deprecation_removal_warning ( :values )
275
+ deprecation_removal_warning ( :values , "errors.map { |error| error.message }" )
253
276
@errors . map ( &:message ) . freeze
254
277
end
255
278
@@ -258,7 +281,7 @@ def values
258
281
# person.errors.messages # => {:name=>["cannot be nil", "must be specified"]}
259
282
# person.errors.keys # => [:name]
260
283
def keys
261
- deprecation_removal_warning ( :keys )
284
+ deprecation_removal_warning ( :keys , "errors.map { |error| error.attribute }" )
262
285
keys = @errors . map ( &:attribute )
263
286
keys . uniq!
264
287
keys . freeze
@@ -338,25 +361,25 @@ def group_by_attribute
338
361
@errors . group_by ( &:attribute )
339
362
end
340
363
341
- # Adds +message+ to the error messages and used validator type to +details + on +attribute+.
364
+ # Adds a new error of +type + on +attribute+.
342
365
# More than one error can be added to the same +attribute+.
343
- # If no +message + is supplied, <tt>:invalid</tt> is assumed.
366
+ # If no +type + is supplied, <tt>:invalid</tt> is assumed.
344
367
#
345
368
# person.errors.add(:name)
346
- # # => ["is invalid"]
369
+ # # Adds <#ActiveModel::Error attribute=name, type= invalid>
347
370
# person.errors.add(:name, :not_implemented, message: "must be implemented")
348
- # # => ["is invalid", "must be implemented"]
371
+ # # Adds <#ActiveModel::Error attribute=name, type=not_implemented,
372
+ # options={:message=>"must be implemented"}>
349
373
#
350
374
# person.errors.messages
351
375
# # => {:name=>["is invalid", "must be implemented"]}
352
376
#
353
- # person.errors.details
354
- # # => {:name=>[{error: :not_implemented}, {error: :invalid}]}
377
+ # If +type+ is a string, it will be used as error message.
355
378
#
356
- # If +message + is a symbol, it will be translated using the appropriate
379
+ # If +type + is a symbol, it will be translated using the appropriate
357
380
# scope (see +generate_message+).
358
381
#
359
- # If +message + is a proc, it will be called, allowing for things like
382
+ # If +type + is a proc, it will be called, allowing for things like
360
383
# <tt>Time.now</tt> to be used within an error.
361
384
#
362
385
# If the <tt>:strict</tt> option is set to +true+, it will raise
@@ -393,14 +416,14 @@ def add(attribute, type = :invalid, **options)
393
416
error
394
417
end
395
418
396
- # Returns +true+ if an error on the attribute with the given message is
397
- # present, or +false+ otherwise. +message + is treated the same as for +add+.
419
+ # Returns +true+ if an error matches provided + attribute+ and +type+,
420
+ # or +false+ otherwise. +type + is treated the same as for +add+.
398
421
#
399
422
# person.errors.add :name, :blank
400
423
# person.errors.added? :name, :blank # => true
401
424
# person.errors.added? :name, "can't be blank" # => true
402
425
#
403
- # If the error message requires options, then it returns +true+ with
426
+ # If the error requires options, then it returns +true+ with
404
427
# the correct options, or +false+ with incorrect or missing options.
405
428
#
406
429
# person.errors.add :name, :too_long, { count: 25 }
@@ -421,8 +444,8 @@ def added?(attribute, type = :invalid, options = {})
421
444
end
422
445
end
423
446
424
- # Returns +true+ if an error on the attribute with the given message is
425
- # present, or +false+ otherwise. +message + is treated the same as for +add+.
447
+ # Returns +true+ if an error on the attribute with the given type is
448
+ # present, or +false+ otherwise. +type + is treated the same as for +add+.
426
449
#
427
450
# person.errors.add :age
428
451
# person.errors.add :name, :too_long, { count: 25 }
@@ -432,13 +455,13 @@ def added?(attribute, type = :invalid, options = {})
432
455
# person.errors.of_kind? :name, "is too long (maximum is 25 characters)" # => true
433
456
# person.errors.of_kind? :name, :not_too_long # => false
434
457
# person.errors.of_kind? :name, "is too long" # => false
435
- def of_kind? ( attribute , message = :invalid )
436
- attribute , message = normalize_arguments ( attribute , message )
458
+ def of_kind? ( attribute , type = :invalid )
459
+ attribute , type = normalize_arguments ( attribute , type )
437
460
438
- if message . is_a? Symbol
439
- !where ( attribute , message ) . empty?
461
+ if type . is_a? Symbol
462
+ !where ( attribute , type ) . empty?
440
463
else
441
- messages_for ( attribute ) . include? ( message )
464
+ messages_for ( attribute ) . include? ( type )
442
465
end
443
466
end
444
467
@@ -550,13 +573,27 @@ def add_from_legacy_details_hash(details)
550
573
}
551
574
end
552
575
553
- def deprecation_removal_warning ( method_name )
554
- ActiveSupport ::Deprecation . warn ( "ActiveModel::Errors##{ method_name } is deprecated and will be removed in Rails 6.2" )
576
+ def deprecation_removal_warning ( method_name , alternative_message = nil )
577
+ message = +"ActiveModel::Errors##{ method_name } is deprecated and will be removed in Rails 6.2."
578
+ if alternative_message
579
+ message << "\n \n To achieve the same use:\n \n "
580
+ message << alternative_message
581
+ end
582
+ ActiveSupport ::Deprecation . warn ( message )
555
583
end
556
584
557
585
def deprecation_rename_warning ( old_method_name , new_method_name )
558
586
ActiveSupport ::Deprecation . warn ( "ActiveModel::Errors##{ old_method_name } is deprecated. Please call ##{ new_method_name } instead." )
559
587
end
588
+
589
+ def deprecation_index_access_warning ( method_name , alternative_message )
590
+ message = +"ActiveModel::Errors##{ method_name } is deprecated. In the next release it would return `Error` object instead."
591
+ if alternative_message
592
+ message << "\n \n To achieve the same use:\n \n "
593
+ message << alternative_message
594
+ end
595
+ ActiveSupport ::Deprecation . warn ( message )
596
+ end
560
597
end
561
598
562
599
class DeprecationHandlingMessageHash < SimpleDelegator
0 commit comments