class AdequateErrors::Error
Represents one single error @!attribute [r] base
@return [ActiveModel::Base] the object which the error belongs to
@!attribute [r] attribute
@return [Symbol] attribute of the object which the error belongs to
@!attribute [r] type
@return [Symbol] error's type
@!attribute [r] options
@return [Hash] additional options
Attributes
Public Class Methods
# File lib/adequate_errors/error.rb, line 12 def initialize(base, attribute, type, options = {}) @base = base @attribute = attribute @type = type @options = options end
Public Instance Methods
@param (see Errors#where
) @return [Boolean] whether error matches the params
# File lib/adequate_errors/error.rb, line 107 def match?(params) if params.key?(:attribute) && @attribute != params[:attribute] return false end if params.key?(:type) && @type != params[:type] return false end (params.keys - [:attribute, :type]).each do |key| if @options[key] != params[key] return false end end true end
Full message of the error.
Key differences to Rails vanilla errors¶ ↑
1. Flexible positioning of attribute name interpolation¶ ↑
In Rails, errors' full messages are always prefixed with attribute name, and if prefix is not wanted, developer often adds error to the `base' attribute instead. This can be unreasonable in different languages or special business requirements.
AdequateErrors
leaves the attribute placement to the developer. For each error message in the locale file, the %{attribute} indicates placement of the attribute. The same error can have prefix in English, and be prefix-less in Russian. If no prefix is needed, one should update the locale file accordingly,
2. Message evaluated lazily¶ ↑
In Rails, error message is evaluated during the `add` call. AdequateErrors
evaluates message lazily at `message` call instead, so one can change message locale after model has been validated.
Order of I18n lookup:¶ ↑
Error
messages are first looked up in activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE
, if it's not there, it's looked up in activemodel.adequate_errors.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 class Admin < User; end
and you wanted the translation for the :blank
error message for the title
attribute, it looks for these translations:
-
activemodel.adequate_errors.models.admin.attributes.title.blank
-
activemodel.adequate_errors.models.admin.blank
-
activemodel.adequate_errors.models.user.attributes.title.blank
-
activemodel.adequate_errors.models.user.blank
-
any default you provided through the
options
hash (in theactivemodel.adequate_errors
scope) -
activemodel.adequate_errors.messages.blank
-
adequate_errors.attributes.title.blank
-
adequate_errors.messages.blank
# File lib/adequate_errors/error.rb, line 65 def message if @options[:message].is_a?(Symbol) type = @options.delete(:message) else type = @type end if @base.class.respond_to?(:i18n_scope) i18n_scope = @base.class.i18n_scope.to_s defaults = @base.class.lookup_ancestors.flat_map do |klass| [ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}", :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ] end defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}" else defaults = [] end defaults << :"adequate_errors.attributes.#{attribute}.#{type}" defaults << :"adequate_errors.messages.#{type}" key = defaults.shift defaults = @options.delete(:message) if @options[:message] value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil) i18n_options = { default: defaults, model: @base.model_name.human, attribute: humanized_attribute, value: value, object: @base, exception_handler: ->(exception, locale, key, option) { rails_errors = @base.errors rails_errors.full_message(@attribute, rails_errors.generate_message(@attribute, @type, @options)) } }.merge!(@options) I18n.translate(key, i18n_options) end
Private Instance Methods
# File lib/adequate_errors/error.rb, line 127 def humanized_attribute default = @attribute.to_s.tr(".", "_").humanize @base.class.human_attribute_name(@attribute, default: default) end