class ActiveModel::Errors

def add(attribute, type = :invalid, **options)

# => {:base=>[{error: :name_or_email_blank}]}
person.errors.details
# => {:base=>["either name or email must be present"]}
person.errors.messages
message: "either name or email must be present")
person.errors.add(:base, :name_or_email_blank,

directly associated with a single attribute.
+attribute+ should be set to :base if the error is not

person.errors.messages # => {}

# => NameIsInvalid: Name is invalid
person.errors.add(:name, :invalid, strict: NameIsInvalid)
# => ActiveModel::StrictValidationFailed: Name is invalid
person.errors.add(:name, :invalid, strict: true)

:strict option can also be set to any other exception.
ActiveModel::StrictValidationFailed instead of adding the error.
If the :strict option is set to +true+, it will raise

Time.now to be used within an error.
If +type+ is a proc, it will be called, allowing for things like

# => ["is too long (maximum is 25 characters)"]
person.errors.messages
person.errors.add(:name, :too_long, { count: 25 })

# => {:name=>["can't be blank"]}
person.errors.messages
person.errors.add(:name, :blank)

scope (see +generate_message+).
If +type+ is a symbol, it will be translated using the appropriate

If +type+ is a string, it will be used as error message.

# => {:name=>["is invalid", "must be implemented"]}
person.errors.messages

options={:message=>"must be implemented"}>
# Adds <#ActiveModel::Error attribute=name, type=not_implemented,
person.errors.add(:name, :not_implemented, message: "must be implemented")
# Adds <#ActiveModel::Error attribute=name, type=invalid>
person.errors.add(:name)

If no +type+ is supplied, :invalid is assumed.
More than one error can be added to the same +attribute+.
Adds a new error of +type+ on +attribute+.
def add(attribute, type = :invalid, **options)
  attribute, type, options = normalize_arguments(attribute, type, **options)
  error = Error.new(@base, attribute, type, **options)
  if exception = options[:strict]
    exception = ActiveModel::StrictValidationFailed if exception == true
    raise exception, error.full_message
  end
  @errors.append(error)
  error
end