Skip to content

Instantly share code, notes, and snippets.

@coorasse
Created October 20, 2020 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coorasse/ecbc8e3a03de147f58438e6d8d2d3fff to your computer and use it in GitHub Desktop.
Save coorasse/ecbc8e3a03de147f58438e6d8d2d3fff to your computer and use it in GitHub Desktop.
An error renderer for ActiveModel models errors
class ErrorsMapper
class << self
def call(model, *prefix)
model.errors.details.map { |attribute, detail| map_details(model, prefix, attribute, detail) }.flatten
end
def single(status: 422, attribute: :base, code: :invalid, message: I18n.t('activerecord.errors.messages.invalid'))
{ status: status, pointer: attribute, code: code, detail: message }
end
private
def map_details(model, prefix, attribute, detail)
detail.map.with_index do |error, index|
if error[:value].respond_to?(:errors)
call(error[:value], [*prefix, attribute])
else
code = error[:error]
message = full_message(model, attribute, index, code)
single(attribute: [*prefix, attribute].compact.join('.'), code: code, message: message)
end
end
end
def full_message(model, attribute, index, code)
message = model.errors.full_message(attribute, model.errors.messages[attribute][index])
message += allowed_values(model, attribute) if code == :inclusion
message
end
def allowed_values(model, attribute)
validator = model.class.
validators_on(attribute).
find { |v| v.is_a?(ActiveModel::Validations::InclusionValidator) }
if validator
values = validator.options[:in]
I18n.t('activerecord.errors.messages.inclusion_addition', values: values.join(', '))
else
''
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment