aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/README32
-rw-r--r--activemodel/lib/active_model/errors.rb107
2 files changed, 139 insertions, 0 deletions
diff --git a/activemodel/README b/activemodel/README
index c8814a9ea3..9af10d8a38 100644
--- a/activemodel/README
+++ b/activemodel/README
@@ -78,3 +78,35 @@ functionality from the following modules:
{Learn more}[link:classes/ActiveModel/Dirty.html]
+* Adding +errors+ support to your object
+
+ Provides the error messages to allow your object to interact with Action Pack
+ helpers seamlessly...
+
+ class Person
+
+ def initialize
+ @errors = ActiveModel::Errors.new(self)
+ end
+
+ attr_accessor :name
+ attr_reader :errors
+
+ def validate!
+ errors.add(:name, "can not be nil") if name == nil
+ end
+
+ def ErrorsPerson.human_attribute_name(attr, options = {})
+ "Name"
+ end
+
+ end
+
+ ... gives you...
+
+ person.errors.full_messages
+ # => ["Name Can not be nil"]
+ person.errors.full_messages
+ # => ["Name Can not be nil"]
+
+ {Learn more}[link:classes/ActiveModel/Errors.html]
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 0b6c75c46e..a51aa9698d 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -2,9 +2,66 @@ require 'active_support/core_ext/string/inflections'
require 'active_support/ordered_hash'
module ActiveModel
+ # Provides a modified +OrderedHash+ that you can include in your object
+ # for handling error messages and interacting with Action Pack helpers.
+ #
+ # A minimal implementation could be:
+ #
+ # class Person
+ #
+ # def initialize
+ # @errors = ActiveModel::Errors.new(self)
+ # end
+ #
+ # attr_accessor :name
+ # attr_reader :errors
+ #
+ # def validate!
+ # errors.add(:name, "can not be nil") if name == nil
+ # end
+ #
+ # # The following methods are needed to be minimally implemented
+ #
+ # def read_attribute_for_validation(attr)
+ # send(attr)
+ # end
+ #
+ # def ErrorsPerson.human_attribute_name(attr, options = {})
+ # attr
+ # end
+ #
+ # def ErrorsPerson.lookup_ancestors
+ # [self]
+ # end
+ #
+ # def ErrorsPerson.model_name
+ # ActiveModel::Name.new(ErrorsPerson)
+ # end
+ #
+ # end
+ #
+ # The last four methods are required in your object for Errors to be
+ # able to generate error messages correctly and also handle multiple
+ # languages.
+ #
+ # The above allows you to do:
+ #
+ # p = Person.new
+ # p.validate! # => ["can not be nil"]
+ # p.errors.full_messages # => ["name can not be nil"]
+ # # etc..
class Errors < ActiveSupport::OrderedHash
include DeprecatedErrorMethods
+ # Pass in the instance of the object that is using the errors object.
+ #
+ # class Person
+ # def initialize
+ # @errors = ActiveModel::Errors.new(self)
+ # end
+ # end
+ #
+ #
def initialize(base)
@base = base
super()
@@ -13,6 +70,10 @@ module ActiveModel
alias_method :get, :[]
alias_method :set, :[]=
+ # When passed a symbol or a name of a method, returns an array of errors for the method.
+ #
+ # p.errors[:name] #=> ["can not be nil"]
+ # p.errors['name'] #=> ["can not be nil"]
def [](attribute)
if errors = get(attribute.to_sym)
errors
@@ -21,28 +82,73 @@ module ActiveModel
end
end
+ # Adds to the supplied attribute the supplied error message.
+ #
+ # p.errors[:name] = "must be set"
+ # p.errors[:name] #=> ['must be set']
def []=(attribute, error)
self[attribute.to_sym] << error
end
+ # Iterates through each error key, value pair in the error messages hash.
+ # Yields the attribute and the error for that attribute. If the attribute
+ # has more than one error message, yields once for each error message.
+ #
+ # p.errors.add(:name, "can't be blank")
+ # p.errors.each do |attribute, errors_array|
+ # # Will yield :name and "can't be blank"
+ # end
+ #
+ # p.errors.add(:name, "must be specified")
+ # p.errors.each do |attribute, errors_array|
+ # # Will yield :name and "can't be blank"
+ # # then yield :name and "must be specified"
+ # end
def each
each_key do |attribute|
self[attribute].each { |error| yield attribute, error }
end
end
+ # Returns the number of error messages.
+ #
+ # p.errors.add(:name, "can't be blank")
+ # p.errors.size #=> 1
+ # p.errors.add(:name, "must be specified")
+ # p.errors.size #=> 2
def size
values.flatten.size
end
+ # Returns an array of error messages, with the attribute name included
+ #
+ # p.errors.add(:name, "can't be blank")
+ # p.errors.add(:name, "must be specified")
+ # p.errors.to_a #=> ["name can't be blank", "name must be specified"]
def to_a
full_messages
end
+ # Returns the number of error messages.
+ # p.errors.add(:name, "can't be blank")
+ # p.errors.count #=> 1
+ # p.errors.add(:name, "must be specified")
+ # p.errors.count #=> 2
def count
to_a.size
end
+ # Returns an xml formatted representation of the Errors hash.
+ #
+ # p.errors.add(:name, "can't be blank")
+ # p.errors.add(:name, "must be specified")
+ # p.errors.to_xml #=> Produces:
+ #
+ # # <?xml version=\"1.0\" encoding=\"UTF-8\"?>
+ # # <errors>
+ # # <error>name can't be blank</error>
+ # # <error>name must be specified</error>
+ # # </errors>
def to_xml(options={})
require 'builder' unless defined? ::Builder
options[:root] ||= "errors"
@@ -59,6 +165,7 @@ module ActiveModel
# for the same attribute and ensure that this error object returns false when asked if <tt>empty?</tt>. More than one
# error can be added to the same +attribute+ in which case an array will be returned on a call to <tt>on(attribute)</tt>.
# If no +messsage+ is supplied, :invalid is assumed.
+ #
# If +message+ is a Symbol, it will be translated, using the appropriate scope (see translate_error).
def add(attribute, message = nil, options = {})
message ||= :invalid