We All Make Mistakes
or Error Handling in Ruby
When running your code, Ruby handles unexpected behavior by raising an exception. There are many different types of exceptions in Ruby and the specific messages they give us are very helpful in debugging our code. With a little bit of knowledge we can add some customization to Ruby’s error handling and use it to help keep our code running even when it encounters a problem.
Everything is an Object!
We know that in Ruby everything is an object. This includes exceptions (which are just instances of the Exception class or one of its descendents). When an exception is raised, execution of the program is stopped and the problem is either dealt with or the program is exited. It us up to us which of these happens.
Ruby to the Rescue
We can tell our program how to handle errors by using a rescue clause. By using the
rescue keyword we can tell our program how to handle an error and keep itself going. The rescue block should feel very familiar to us, because its similar to other conditional statements we are already used to writing. The block starts with the
begin keyword (which can be omitted inside of a method if we just want to use the method as the scope of our rescue) and contains a rescue statement, which tells Ruby what to do if it encounters a problem. Then the whole block is closed by an
This is great, but its also a little broad, we can do better…
We don’t want to rescue from every exception, because this would include some situations where we actually want our program to terminate, like a
NoMemoryError. So how do we get more control? We can refine what we have above by specifying an exception class in the rescue statement, this will cause the rescue to be triggered by any exception that is an instance of the class specified or any of its children. Since most of the errors that we want to control for come from the
StandardError class, this is a good place to start. However, we can be as broad or specific as we want to be customizing the action taken to respond to whatever we specify.
but wait, there’s more!
We can also capture the exception as a variable by assigning it in the rescue statement. This allows us to treat it like we would any instance of a class.
If we want to get even fancier, we can even tell Ruby to raise exceptions in our code in situations where it normally wouldn’t by using the raise keyword.
When you combine this with the fact that you can create your own exception classes, you have a powerful tool for handling unexpected situations in your code.
My Own Exception Classes?
Remember how we said exceptions are just instances of the
Exception class? Well, just like anywhere else, we can create our own exception classes by inheriting from
Exception or one of its children like
StandardError. By doing this we can give new names to exceptions and customize how they are documented and what information is provided. We can also target specific errors that we define ourselves, allowing us to rescue in very controlled ways.
By combining all of this functionality we have an extremely powerful and customizable tool for dealing with the unexpected and keeping our program from crashing when it encounters something unexpected.