From bc818e4bc52efb005051662ab0536790f62b1122 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Fri, 22 Jun 2012 11:52:57 -0500 Subject: [PATCH] update ActiveModel::Errors documentation and minor fixes [ci skip] --- activemodel/lib/active_model/conversion.rb | 2 +- activemodel/lib/active_model/dirty.rb | 6 +- activemodel/lib/active_model/errors.rb | 159 +++++++++++++-------- 3 files changed, 103 insertions(+), 64 deletions(-) diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb index 43d248e5cb..89d87a8b6f 100644 --- a/activemodel/lib/active_model/conversion.rb +++ b/activemodel/lib/active_model/conversion.rb @@ -27,7 +27,7 @@ module ActiveModel # If your object is already designed to implement all of the Active Model # you can use the default :to_model implementation, which simply - # returns self. + # returns +self+. # # class Person # include ActiveModel::Conversion diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index 7014d8114f..9bd5f903cd 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -80,8 +80,8 @@ module ActiveModel # person.changes # => {"name" => ["Bill", "Bob"]} # # If an attribute is modified in-place then make use of [attribute_name]_will_change! - # to mark that the attribute is changing. Otherwise ActiveModel can't track changes to - # in-place attributes. + # to mark that the attribute is changing. Otherwise ActiveModel can't track + # changes to in-place attributes. # # person.name_will_change! # person.name_change # => ["Bill", "Bill"] @@ -115,7 +115,7 @@ module ActiveModel end # Returns a hash of changed attributes indicating their original - # and new values like attr => [original value, new value]. + # and new values like attr => [original value, new value]. # # person.changes # => {} # person.name = 'bob' diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index aba6618b56..e879e931d6 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -54,8 +54,8 @@ module ActiveModel # The above allows you to do: # # p = Person.new - # p.validate! # => ["can not be nil"] - # p.errors.full_messages # => ["name can not be nil"] + # person.validate! # => ["can not be nil"] + # person.errors.full_messages # => ["name can not be nil"] # # etc.. class Errors include Enumerable @@ -81,28 +81,49 @@ module ActiveModel super end - # Clear the messages + # Clear the error messages. + # + # person.errors.full_messages # => ["name can not be nil"] + # person.errors.clear + # person.errors.full_messages # => [] def clear messages.clear end - # Do the error messages include an error with key +error+? + # Returns +true+ if the error messages include an error for the given key + # +error+, +false+ otherwise. + # + # person.errors.messages # => { :name => ["can not be nil"] } + # person.errors.include?(:name) # => true + # person.errors.include?(:age) # => false def include?(error) (v = messages[error]) && v.any? end alias :has_key? :include? - # Get messages for +key+ + # Get messages for +key+. + # + # person.errors.messages # => { :name => ["can not be nil"] } + # person.errors.get(:name) # => ["can not be nil"] + # person.errors.get(:age) # => nil def get(key) messages[key] end - # Set messages for +key+ to +value+ + # Set messages for +key+ to +value+. + # + # person.errors.get(:name) # => ["can not be nil"] + # person.errors.set(:name, ["can't be nil"]) + # person.errors.get(:name) # => ["can't be nil"] def set(key, value) messages[key] = value end - # Delete messages for +key+ + # 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) # => nil def delete(key) messages.delete(key) end @@ -110,16 +131,16 @@ module ActiveModel # 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"] + # person.errors[:name] # => ["can not be nil"] + # person.errors['name'] # => ["can not be nil"] def [](attribute) get(attribute.to_sym) || set(attribute.to_sym, []) end # Adds to the supplied attribute the supplied error message. # - # p.errors[:name] = "must be set" - # p.errors[:name] # => ['must be set'] + # person.errors[:name] = "must be set" + # person.errors[:name] # => ['must be set'] def []=(attribute, error) self[attribute] << error end @@ -128,13 +149,13 @@ module ActiveModel # 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, error| + # person.errors.add(:name, "can't be blank") + # person.errors.each do |attribute, error| # # Will yield :name and "can't be blank" # end # - # p.errors.add(:name, "must be specified") - # p.errors.each do |attribute, error| + # person.errors.add(:name, "must be specified") + # person.errors.each do |attribute, error| # # Will yield :name and "can't be blank" # # then yield :name and "must be specified" # end @@ -146,44 +167,54 @@ module ActiveModel # 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 + # person.errors.add(:name, "can't be blank") + # person.errors.size # => 1 + # person.errors.add(:name, "must be specified") + # person.errors.size # => 2 def size values.flatten.size end - # Returns all message values + # 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"]] def values messages.values end - # Returns all message keys + # Returns all message keys. + # + # person.errors.messages # => { :name => ["can not be nil", "must be specified"] } + # person.errors.keys # => [:name] def keys messages.keys end - # Returns an array of error messages, with the attribute name included + # 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"] + # person.errors.add(:name, "can't be blank") + # person.errors.add(:name, "must be specified") + # person.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 + # + # person.errors.add(:name, "can't be blank") + # person.errors.count # => 1 + # person.errors.add(:name, "must be specified") + # person.errors.count # => 2 def count to_a.size end - # Returns true if no errors are found, false otherwise. + # 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.empty? # => false def empty? all? { |k, v| v && v.empty? && !v.is_a?(String) } end @@ -191,9 +222,9 @@ module ActiveModel # 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 + # person.errors.add(:name, "can't be blank") + # person.errors.add(:name, "must be specified") + # person.errors.to_xml # # => # # # # @@ -204,10 +235,13 @@ module ActiveModel to_a.to_xml({ :root => "errors", :skip_types => true }.merge!(options)) end - # Returns an Hash that can be used as the JSON representation for this object. - # Options: - # * :full_messages - determines if json object should contain - # full messages or not. Default: false. + # Returns an Hash that can be used as the JSON representation for this + # object. Also, You can pass the :full_messages 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"] } def as_json(options=nil) to_hash(options && options[:full_messages]) end @@ -224,12 +258,15 @@ module ActiveModel end end - # Adds +message+ to the error messages on +attribute+. More than one error can be added to the same - # +attribute+. - # If no +message+ is supplied, :invalid is assumed. + # Adds +message+ to the error messages on +attribute+. More than one error + # can be added to the same +attribute+. If no +message+ is supplied, + # :invalid is assumed. # - # If +message+ is a symbol, it will be translated using the appropriate scope (see +generate_message+). - # If +message+ is a proc, it will be called, allowing for things like Time.now to be used within an error. + # If +message+ is a symbol, it will be translated using the appropriate + # scope (see +generate_message+). + # + # If +message+ is a proc, it will be called, allowing for things like + # Time.now to be used within an error. def add(attribute, message = nil, options = {}) message = normalize_message(attribute, message, options) if options[:strict] @@ -239,7 +276,8 @@ module ActiveModel self[attribute] << message end - # Will add an error message to each of the attributes in +attributes+ that is empty. + # Will add an error message to each of the attributes in +attributes+ + # that is empty. def add_on_empty(attributes, options = {}) [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) @@ -248,7 +286,8 @@ module ActiveModel end end - # Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?). + # Will add an error message to each of the attributes in +attributes+ that + # is blank (using Object#blank?). def add_on_blank(attributes, options = {}) [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) @@ -256,10 +295,11 @@ module ActiveModel end end - # Returns true if an error on the attribute with the given message is present, false otherwise. - # +message+ is treated the same as for +add+. - # p.errors.add :name, :blank - # p.errors.added? :name, :blank # => true + # Returns +true+ if an error on the attribute with the given message is + # present, +false+ otherwise. +message+ is treated the same as for +add+. + # + # person.errors.add :name, :blank + # person.errors.added? :name, :blank # => true def added?(attribute, message = nil, options = {}) message = normalize_message(attribute, message, options) self[attribute].include? message @@ -267,22 +307,21 @@ module ActiveModel # Returns all the full error messages in an array. # - # class Company + # class Person # validates_presence_of :name, :address, :email - # validates_length_of :name, :in => 5..30 + # validates_length_of :name, in: 5..30 # end # - # company = Company.create(:address => '123 First St.') - # company.errors.full_messages # => - # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"] + # person = Person.create(address: '123 First St.') + # person.errors.full_messages + # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"] def full_messages map { |attribute, message| full_message(attribute, message) } end # Returns a full message for a given attribute. # - # company.errors.full_message(:name, "is invalid") # => - # "Name is invalid" + # 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 @@ -298,10 +337,11 @@ module ActiveModel # (activemodel.errors.messages). # # Error messages are first looked up in models.MODEL.attributes.ATTRIBUTE.MESSAGE, - # if it's not there, it's looked up in models.MODEL.MESSAGE and if that is not - # there also, it returns the translation of the default message - # (e.g. activemodel.errors.messages.MESSAGE). The translated model name, - # translated attribute name and the value are available for interpolation. + # if it's not there, it's looked up in models.MODEL.MESSAGE and if + # that is not there also, it returns the translation of the default message + # (e.g. activemodel.errors.messages.MESSAGE). The translated model + # name, translated attribute name and the value are available for + # interpolation. # # When using inheritance in your models, it will check all the inherited # models too, but only if the model itself hasn't been found. Say you have @@ -317,7 +357,6 @@ module ActiveModel # * activemodel.errors.messages.blank # * errors.attributes.title.blank # * errors.messages.blank - # def generate_message(attribute, type = :invalid, options = {}) type = options.delete(:message) if options[:message].is_a?(Symbol)