diff options
Diffstat (limited to 'activemodel/lib/active_model/errors.rb')
-rw-r--r-- | activemodel/lib/active_model/errors.rb | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 685e235730..2f883917b0 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -71,8 +71,8 @@ module ActiveModel # end def initialize(base) @base = base - @messages = Hash.new { |messages, attribute| messages[attribute] = [] } - @details = Hash.new { |details, attribute| details[attribute] = [] } + @messages = apply_default_array({}) + @details = apply_default_array({}) end def initialize_dup(other) # :nodoc: @@ -147,9 +147,9 @@ module ActiveModel # Delete messages for +key+. Returns the deleted messages. # - # person.errors[:name] # => ["cannot be nil"] + # person.errors[:name] # => ["cannot be nil"] # person.errors.delete(:name) # => ["cannot be nil"] - # person.errors[:name] # => [] + # person.errors[:name] # => [] def delete(key) details.delete(key) messages.delete(key) @@ -310,9 +310,9 @@ module ActiveModel # <tt>:strict</tt> option can also be set to any other exception. # # person.errors.add(:name, :invalid, strict: true) - # # => ActiveModel::StrictValidationFailed: name is invalid + # # => ActiveModel::StrictValidationFailed: Name is invalid # person.errors.add(:name, :invalid, strict: NameIsInvalid) - # # => NameIsInvalid: name is invalid + # # => NameIsInvalid: Name is invalid # # person.errors.messages # => {} # @@ -382,10 +382,21 @@ module ActiveModel 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+. + # present, or +false+ otherwise. +message+ is treated the same as for +add+. # # person.errors.add :name, :blank - # person.errors.added? :name, :blank # => true + # person.errors.added? :name, :blank # => true + # person.errors.added? :name, "can't be blank" # => true + # + # If the error message requires an option, then it returns +true+ with + # the correct option, or +false+ with an incorrect or missing option. + # + # person.errors.add :name, :too_long, { count: 25 } + # person.errors.added? :name, :too_long, count: 25 # => true + # person.errors.added? :name, "is too long (maximum is 25 characters)" # => true + # person.errors.added? :name, :too_long, count: 24 # => false + # person.errors.added? :name, :too_long # => false + # person.errors.added? :name, "is too long" # => false def added?(attribute, message = :invalid, options = {}) message = message.call if message.respond_to?(:call) message = normalize_message(attribute, message, options) @@ -493,6 +504,16 @@ module ActiveModel I18n.translate(key, options) end + def marshal_dump + [@base, without_default_proc(@messages), without_default_proc(@details)] + end + + def marshal_load(array) + @base, @messages, @details = array + apply_default_array(@messages) + apply_default_array(@details) + end + private def normalize_message(attribute, message, options) case message @@ -506,6 +527,17 @@ module ActiveModel def normalize_detail(message, options) { error: message }.merge(options.except(*CALLBACKS_OPTIONS + MESSAGE_OPTIONS)) end + + def without_default_proc(hash) + hash.dup.tap do |new_h| + new_h.default_proc = nil + end + end + + def apply_default_array(hash) + hash.default_proc = proc { |h, key| h[key] = [] } + hash + end end # Raised when a validation cannot be corrected by end users and are considered @@ -531,6 +563,15 @@ module ActiveModel end # Raised when unknown attributes are supplied via mass assignment. + # + # class Person + # include ActiveModel::AttributeAssignment + # include ActiveModel::Validations + # end + # + # person = Person.new + # person.assign_attributes(name: 'Gorby') + # # => ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person. class UnknownAttributeError < NoMethodError attr_reader :record, :attribute |