Reputation: 665
If I create an app in rails using the --api flag my error responses are in html rather than json.
How am I able to change the default error handler so that whenever an error is thrown in a controller action, I receive a json only response with the error and http status?
right now I am using the code below in every custom action
rescue => e
response.status = 422
render json: { error: e.message }
I'd rather not have to add this each time...
UPDATE: I used the rescue_from method in the application controller
rescue_from Exception do |exception|
render json: exception, status: 500
end
But I feel this is very wrong and the status will always be hard coded as 500
Upvotes: 5
Views: 9107
Reputation: 1212
You can use the api_error_handler gem.
Include it in your bundler file:
gem "api_error_handler", "~> 0.2.0"
The in your application controller, invoke the library.
class ApplicationController < ActionController::API
handle_api_errors(
# Error handling options go here if you want to override any defaults.
)
# ...
end
Now if you have a controller like this:
class UsersController < ApplicationController
def index
raise 'SOMETHING WENT WRONG!!!'
end
end
When you hit this endpoint you will see this response
{
"error": {
"title": "Internal Server Error",
"detail": "SOMETHING WENT WRONG!!!"
}
}
And the status code will be set to an appropriate status code based on the type of error you had.
See the gem's README for more info on how to configure the error response.
Upvotes: 0
Reputation: 7361
you can add format as json in routes so it will always accept request in json format like below
namespace :api, as: nil, defaults: { format: :json } do
devise_for :users, controllers: {
registrations: "api/v1/users/registrations",
passwords: "api/v1/users/passwords"
}
resources :products, only: [:show,:index] do
get "check_product_avaibility"
get "filter", on: :collection
end
end
For handling errors globally, you can add around_action in application controller file
around_action :handle_exceptions, if: proc { request.path.include?('/api') }
# Catch exception and return JSON-formatted error
def handle_exceptions
begin
yield
rescue ActiveRecord::RecordNotFound => e
@status = 404
@message = 'Record not found'
rescue ActiveRecord::RecordInvalid => e
render_unprocessable_entity_response(e.record) && return
rescue ArgumentError => e
@status = 400
rescue StandardError => e
@status = 500
end
json_response({ success: false, message: @message || e.class.to_s, errors: [{ detail: e.message }] }, @status) unless e.class == NilClass
end
NOTE: render_unprocessable_entity_response and json_response are custom methods , you can add your own methods to render json response.
Upvotes: 6