Created
November 30, 2015 20:46
-
-
Save fespinoza/3c75877aedccef709dde to your computer and use it in GitHub Desktop.
Error Normalization Concern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ErrorNormalization | |
extend ActiveSupport::Concern | |
included do | |
rescue_from CanCan::AccessDenied, with: :render_forbidden | |
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found | |
rescue_from ActionController::ParameterMissing, with: :render_bad_request | |
end | |
def render_forbidden | |
build_and_render_api_error(403, :forbidden) | |
end | |
def render_not_found(exception) | |
message = normalize_not_found_message(exception) | |
build_and_render_api_error(404, :not_found, message: message) | |
end | |
def render_bad_request(exception) | |
build_and_render_api_error(400, :bad_request, message: exception.message) | |
end | |
def render_show_or_errors(object, status: 200) | |
respond_to do |format| | |
format.json do | |
if object.valid? | |
render :show, status: status | |
else | |
render_api_error(build_validation_error(object)) | |
end | |
end | |
end | |
end | |
def build_validation_error(object) | |
options = { validation_errors: object.errors } | |
build_api_error(422, :unprocessable_entity, options) | |
end | |
def build_api_error(status_code, error_identifier, options = {}) | |
options[:subdomain] ||= organization_identifier | |
API::Error.new(status_code, error_identifier, options) | |
end | |
def render_api_error(api_error) | |
render json: api_error, status: api_error.status | |
end | |
def build_and_render_api_error(status_code, error_identifier, options = {}) | |
api_error = build_api_error(status_code, error_identifier, options) | |
render_api_error(api_error) | |
end | |
private | |
def normalize_not_found_message(exception) | |
message = exception.message | |
match = message.match(/Couldn't find (?<class_name>[^\s]+)/) | |
if match | |
class_name = match[:class_name].split('::').last | |
message = I18n.t :not_found, | |
scope: [:api, :errors, :messages], | |
class_name: class_name | |
end | |
message | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment