I love the concept and usability of an ActiveModel::Errors paradigm. However, I and others often find it frustrating to work with the implementation.
I'd love to see a proper ActiveModel::Error
object, where the errors attribute of a model including ActiveModel::Errors was an Enumerator of these objects.
There are various implied benefits and added flexibility that could be introduced in a backwards compatible way later, and immedate benefits.
APIs we build prefer to return Error
objects to clients with the following schema:
{
attribute: "The model attribute to which the error applies. If blank, the error applies generically to the base model.",
type: "The type of error encountered with the model attribute or model."
messsage: "An internationalized message that can be displayed to a user.",
}
In particular, the type
attribute allows clients to couple any logic they need on the error attribute
and type
, not the message
, which should be able to change with business/product needs.
With a proper ActiveModel::Error
object, this is easily done. With the current enumerable design, this is not a clean extension to make.
Currently, the message interpolation is looked up when the error is added to the model. This isn't necessarry, and is easily lazily evaluated when a derived attribute on an Error
object.
error = model.errors.first
error.attribute
=> :username
error.attribute_value
=> 'eprothro'
# en.yml
errors:
models:
user:
attributes:
username:
taken: "%{value} has already been taken."