Reputation: 5528
When an error occurs in Rails API Only, the server responds with an error in json with the following format: {"status":500,"error":"Internal Server Error"}
.
The format is the same for other errors as well: {"status":404,"error":"Not Found"}
.
I want to render the errors with the format: {"errors": [{status: 404, title: "Not found"}]}
.
Basically I want to change the format of all errors to be the same and I don't find a way to do that.
I know I can use (for example) rescue_from ActiveRecord::RecordNotFound, with: :my_method
and override the single exceptions but this means I have to list all possible exceptions and return the appropriate code, when Rails is already doing that.
What I am looking for is a method that can be overridden, and that I can use to change the "default" error format of Rails.
Upvotes: 5
Views: 2169
Reputation: 5528
You can configure an exceptions_app in Rails.
The default Middleware which manages exceptions and render the errors is ActionDispatch::PublicExceptions
.
First thing is to override this middleware to implement our custom behavior. Inside app/middlewares/action_dispatch
folder create a public_exceptions_plus.rb
file with the following:
module ActionDispatch
class PublicExceptionsPlus < PublicExceptions
def call(env)
request = ActionDispatch::Request.new(env)
status = request.path_info[1..-1].to_i
content_type = request.formats.first
# define here your custom format
body = { errors: [{ status: status,
title: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }] }
render(status, content_type, body)
end
end
end
after that, inside config/application.rb
add the following:
config.exceptions_app = ->(env) { ActionDispatch::PublicExceptionsPlus.new(Rails.public_path).call(env) }
Thanks @smallbutton.com for the input. I think this is a better solution since it does not require a controller but just a middleware.
Upvotes: 3
Reputation: 3437
The best way to do this in Rails is probably defining an exceptions_app
(see config.exceptions_app)
which must be a custom rack app. This will let you render your exceptions however you choose. An example can be found here.
config.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }
class ErrorsController < ApplicationController
layout 'error'
def show
exception = env['action_dispatch.exception']
status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code
# render whatever you want here
end
end
You can also check what the default implementation by rails is.
There is also a gem called exception_handler
that might be an alternative here.
More resources: https://devblast.com/b/jutsu-12-custom-error-pages-in-rails-4
Upvotes: 7