Often times I have seen programmers raise custom exceptions as raise 'User is not authenticated' which is a very simple and readable approach but, does not have a well-defined structure to it. These are just strings littered all across your application and sometimes these strings get really really long. Ughh!
Another way to raise custom exceptions is by first defining a sub-class inheriting StandardError and then raising it as shown below.
Both the approaches are limited in scope as to what the error conveys. Also, forget about adding extra details in the errors like user-friendly messages, custom error codes, HTTP codes(if needed), etc.
But, then you might be wondering, why even need these details? Good thought ;) For a moment consider that the errors raised by your application does respond tocode, message and http_code.
Since we know every error message contains these details we can capture it in a single place in our application_controller.rb and respond to it in a generic fashion. This kind of elegance is very useful in the long run since it promotes reusability and you don’t have to handle errors in every controller. Just raise the custom exception and it will be handled automatically. Below is an example error handler in an example api/application_controller.rb file.
Now, that we have an idea of why we need such a system in place let’s get into how to do it.
Firstly, we do not want to create classes for every custom error and secondly, we want to make our errors declarative in a configuration file with the required details and it should be usable by the application.
The best solution(at least the one that I could come up with) is using some meta-programming magic(specifically const_missing) which should do the following
Determine the exception our application is raising
Find the details in the configuration file
Create the error object
The ApplicationError class now can be used to raise any kind of custom error as long as they have been configured in the errors.en.yml file inside of the error section. An example of an errors.en.yml file is given below.
After the errors have been declared in the errors.en.yml file we can raise them as
While inheritance is one form of extension it is not always the best way to achieve flexibility in our designs. In certain cases you might want to add a number of different responsibilities to a base class.
Abhishek Sarkar
On Software Design, Architecture, Ruby, Ruby On Rails, JavaScript, Node.js, AngularJS and more...