aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/errors.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/lib/active_model/errors.rb')
-rw-r--r--activemodel/lib/active_model/errors.rb105
1 files changed, 61 insertions, 44 deletions
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 963e52bff3..55687cb3c7 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -7,12 +7,11 @@ module ActiveModel
# == Active \Model \Errors
#
# Provides a modified +Hash+ that you can include in your object
- # for handling error messages and interacting with Action Pack helpers.
+ # for handling error messages and interacting with Action View helpers.
#
# A minimal implementation could be:
#
# class Person
- #
# # Required dependency for ActiveModel::Errors
# extend ActiveModel::Naming
#
@@ -24,7 +23,7 @@ module ActiveModel
# attr_reader :errors
#
# def validate!
- # errors.add(:name, "can not be nil") if name == nil
+ # errors.add(:name, "cannot be nil") if name.nil?
# end
#
# # The following methods are needed to be minimally implemented
@@ -40,7 +39,6 @@ module ActiveModel
# def Person.lookup_ancestors
# [self]
# end
- #
# end
#
# The last three methods are required in your object for Errors to be
@@ -52,9 +50,9 @@ module ActiveModel
#
# The above allows you to do:
#
- # p = Person.new
- # person.validate! # => ["can not be nil"]
- # person.errors.full_messages # => ["name can not be nil"]
+ # person = Person.new
+ # person.validate! # => ["cannot be nil"]
+ # person.errors.full_messages # => ["name cannot be nil"]
# # etc..
class Errors
include Enumerable
@@ -82,7 +80,7 @@ module ActiveModel
# Clear the error messages.
#
- # person.errors.full_messages # => ["name can not be nil"]
+ # person.errors.full_messages # => ["name cannot be nil"]
# person.errors.clear
# person.errors.full_messages # => []
def clear
@@ -92,19 +90,21 @@ module ActiveModel
# Returns +true+ if the error messages include an error for the given key
# +attribute+, +false+ otherwise.
#
- # person.errors.messages # => {:name=>["can not be nil"]}
+ # person.errors.messages # => {:name=>["cannot be nil"]}
# person.errors.include?(:name) # => true
# person.errors.include?(:age) # => false
def include?(attribute)
- (v = messages[attribute]) && v.any?
+ messages[attribute].present?
end
# aliases include?
alias :has_key? :include?
+ # aliases include?
+ alias :key? :include?
# Get messages for +key+.
#
- # person.errors.messages # => {:name=>["can not be nil"]}
- # person.errors.get(:name) # => ["can not be nil"]
+ # person.errors.messages # => {:name=>["cannot be nil"]}
+ # person.errors.get(:name) # => ["cannot be nil"]
# person.errors.get(:age) # => nil
def get(key)
messages[key]
@@ -112,7 +112,7 @@ module ActiveModel
# Set messages for +key+ to +value+.
#
- # person.errors.get(:name) # => ["can not be nil"]
+ # person.errors.get(:name) # => ["cannot be nil"]
# person.errors.set(:name, ["can't be nil"])
# person.errors.get(:name) # => ["can't be nil"]
def set(key, value)
@@ -121,8 +121,8 @@ module ActiveModel
# Delete messages for +key+. Returns the deleted messages.
#
- # person.errors.get(:name) # => ["can not be nil"]
- # person.errors.delete(:name) # => ["can not be nil"]
+ # person.errors.get(:name) # => ["cannot be nil"]
+ # person.errors.delete(:name) # => ["cannot be nil"]
# person.errors.get(:name) # => nil
def delete(key)
messages.delete(key)
@@ -131,8 +131,8 @@ module ActiveModel
# When passed a symbol or a name of a method, returns an array of errors
# for the method.
#
- # person.errors[:name] # => ["can not be nil"]
- # person.errors['name'] # => ["can not be nil"]
+ # person.errors[:name] # => ["cannot be nil"]
+ # person.errors['name'] # => ["cannot be nil"]
def [](attribute)
get(attribute.to_sym) || set(attribute.to_sym, [])
end
@@ -177,15 +177,15 @@ module ActiveModel
# Returns all message values.
#
- # person.errors.messages # => {:name=>["can not be nil", "must be specified"]}
- # person.errors.values # => [["can not be nil", "must be specified"]]
+ # person.errors.messages # => {:name=>["cannot be nil", "must be specified"]}
+ # person.errors.values # => [["cannot be nil", "must be specified"]]
def values
messages.values
end
# Returns all message keys.
#
- # person.errors.messages # => {:name=>["can not be nil", "must be specified"]}
+ # person.errors.messages # => {:name=>["cannot be nil", "must be specified"]}
# person.errors.keys # => [:name]
def keys
messages.keys
@@ -213,7 +213,7 @@ module ActiveModel
# Returns +true+ if no errors are found, +false+ otherwise.
# If the error message is a string it can be empty.
#
- # person.errors.full_messages # => ["name can not be nil"]
+ # person.errors.full_messages # => ["name cannot be nil"]
# person.errors.empty? # => false
def empty?
all? { |k, v| v && v.empty? && !v.is_a?(String) }
@@ -233,15 +233,15 @@ module ActiveModel
# # <error>name must be specified</error>
# # </errors>
def to_xml(options={})
- to_a.to_xml({ :root => "errors", :skip_types => true }.merge!(options))
+ to_a.to_xml({ root: "errors", skip_types: true }.merge!(options))
end
# Returns a Hash that can be used as the JSON representation for this
# object. You can pass the <tt>:full_messages</tt> option. This determines
# if the json object should contain full messages or not (false by default).
#
- # person.as_json # => {:name=>["can not be nil"]}
- # person.as_json(full_messages: true) # => {:name=>["name can not be nil"]}
+ # person.errors.as_json # => {:name=>["cannot be nil"]}
+ # person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]}
def as_json(options=nil)
to_hash(options && options[:full_messages])
end
@@ -249,15 +249,13 @@ module ActiveModel
# Returns a Hash of attributes with their error messages. If +full_messages+
# is +true+, it will contain full messages (see +full_message+).
#
- # person.to_hash # => {:name=>["can not be nil"]}
- # person.to_hash(true) # => {:name=>["name can not be nil"]}
+ # person.errors.to_hash # => {:name=>["cannot be nil"]}
+ # person.errors.to_hash(true) # => {:name=>["name cannot be nil"]}
def to_hash(full_messages = false)
if full_messages
- messages = {}
- self.messages.each do |attribute, array|
+ self.messages.each_with_object({}) do |(attribute, array), messages|
messages[attribute] = array.map { |message| full_message(attribute, message) }
end
- messages
else
self.messages.dup
end
@@ -281,17 +279,24 @@ module ActiveModel
# If +message+ is a proc, it will be called, allowing for things like
# <tt>Time.now</tt> to be used within an error.
#
- # If the <tt>:strict</tt> option is set to true will raise
+ # If the <tt>:strict</tt> option is set to +true+, it will raise
# ActiveModel::StrictValidationFailed instead of adding the error.
# <tt>:strict</tt> option can also be set to any other exception.
#
- # person.errors.add(:name, nil, strict: true)
+ # person.errors.add(:name, :invalid, strict: true)
# # => ActiveModel::StrictValidationFailed: name is invalid
- # person.errors.add(:name, nil, strict: NameIsInvalid)
+ # person.errors.add(:name, :invalid, strict: NameIsInvalid)
# # => NameIsInvalid: name is invalid
#
# person.errors.messages # => {}
- def add(attribute, message = nil, options = {})
+ #
+ # +attribute+ should be set to <tt>:base</tt> if the error is not
+ # directly associated with a single attribute.
+ #
+ # person.errors.add(:base, "either name or email must be present")
+ # person.errors.messages
+ # # => {:base=>["either name or email must be present"]}
+ def add(attribute, message = :invalid, options = {})
message = normalize_message(attribute, message, options)
if exception = options[:strict]
exception = ActiveModel::StrictValidationFailed if exception == true
@@ -333,7 +338,7 @@ module ActiveModel
#
# person.errors.add :name, :blank
# person.errors.added? :name, :blank # => true
- def added?(attribute, message = nil, options = {})
+ def added?(attribute, message = :invalid, options = {})
message = normalize_message(attribute, message, options)
self[attribute].include? message
end
@@ -352,17 +357,31 @@ module ActiveModel
map { |attribute, message| full_message(attribute, message) }
end
+ # Returns all the full error messages for a given attribute in an array.
+ #
+ # class Person
+ # validates_presence_of :name, :email
+ # validates_length_of :name, in: 5..30
+ # end
+ #
+ # person = Person.create()
+ # person.errors.full_messages_for(:name)
+ # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
+ def full_messages_for(attribute)
+ (get(attribute) || []).map { |message| full_message(attribute, message) }
+ end
+
# Returns a full message for a given attribute.
#
# person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
def full_message(attribute, message)
return message if attribute == :base
attr_name = attribute.to_s.tr('.', '_').humanize
- attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
+ attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
I18n.t(:"errors.format", {
- :default => "%{attribute} %{message}",
- :attribute => attr_name,
- :message => message
+ default: "%{attribute} %{message}",
+ attribute: attr_name,
+ message: message
})
end
@@ -414,10 +433,10 @@ module ActiveModel
value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)
options = {
- :default => defaults,
- :model => @base.class.model_name.human,
- :attribute => @base.class.human_attribute_name(attribute),
- :value => value
+ default: defaults,
+ model: @base.model_name.human,
+ attribute: @base.class.human_attribute_name(attribute),
+ value: value
}.merge!(options)
I18n.translate(key, options)
@@ -425,8 +444,6 @@ module ActiveModel
private
def normalize_message(attribute, message, options)
- message ||= :invalid
-
case message
when Symbol
generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS))