- Version 0.2.10 released to rubygems on 10.27.2015
- Added support for exceptions that define a http_status.
The exception map can override this.
This is a good way to allow a raise to specify a http_status using a custom exception.
The idea for this came from the Stripe::Error exception classes.
- Added support for exceptions that define a http_status.
Egregious is a rails based exception handling gem for well defined http exception handling for json, xml and html.
If you have a json or xml api into your rails application, you probably have added your own exception handling to map exceptions to a http status and formatting your json and xml output.
You probably have code sprinkled about like this:
This example is straight from the CanCan docs. You’ll notice a couple of things here. This handles the CanCan::AccessDenied exception only. It then will redirect to the startup page, or render xml and json returning the http status code of :forbidden (403). You can see one of the first features of the Egregious gem. We extend Exception to add the to_xml and to_json methods. These return a well structured error that can be consumed by the API client.
returns:
returns:
So that’s pretty handy in itself. Now all exceptions have a json and xml api that describe them. It happens to be the same xml and json that is returned from the errors active record object, with the addition of the type element. That allows you to mix and match validations and exceptions. Wow, big deal. We’ll it is. If you are writing a client then you need to have a very well defined error handling. I’d like to see all of rails do this by default. So that anyone interacting with a rails resource has a consistent error handling experience. (Expect more on being a good REST API in future posts.) As a client we can now handle errors in a consistent way.
Besides the error message we would like a well defined mapping of classes of exceptions to http status codes. The idea is that if I get back a specific http status code then I can program against that ‘class’ of problems. For example if I know that what I did was because of invalid input from my user, I can display that message back to the user. They can correct it and continue down the path. But if the Http status code says that it was a problem with the server, then I know that I need to log it and notify someone to see how to resolve it.
We handle all exceptions of a given class with a mapping to an http status code. With all the most common Ruby, Rails, Devise, Warden and CanCan exceptions having reasonable defaults. (Devise, Warden and CanCan are all optional and ignored if their gems are not installed.)
As of 0.2.9 you can also define a method named ‘http_status’ on the exception and it will be used as the status code. This is a nice pattern that allows you to raise an exception and specify the status code. The Egregious::Error allows you to do this as a second parameter to initialize:
If the problem was the api caller then the result codes are in the 300 range. If the problem was on the server then the status codes are in the 500 range.
I’m guessing if you bother to read this far, you are probably interested in using Egregious. Its simple to use and configure. To install:
In you Gemfile add the following:
In your ApplicationController class add the following at or near the top:
That’s it. You will now get reasonable api error handling.
If you want to add your own exceptions to http status codes end mappings, or change the defaults add an initializer and put the following into it:
Here you can re-map anything and you can add new mappings.
Note: If you think the default exception mappings should be different, please contact me via the Egregious github project.
We also created exceptions for each of the http status codes, so that you can throw those exceptions in your code. Its an easy way to throw the right status code and setup a good message for it. If you want to provide more context, you can derive you own exceptions and add mappings for them.
Here is an example of throwing a bad request exception:
Egregious adds mapping of many exceptions, if you have your own rescue_from handlers those will get invoked. You will not lose any existing behavior, but you also might not see the changes you expect until you remove or modify those rescue_from calls. At a minimum I suggest using the .to_xml and .to_json calls io your existing rescue_from methods/blocks.
And finally if you don’t like the default behavior. You can override any portion of it and change it to meet your needs.
If you want to change the behavior then you can override the following methods in your ApplicationController.
We are using this gem in all our Rails projects.
Go forth and be egregious!