What is an Exception?
Exceptions are an exceptional state in the course of the code. It’s a way for the programming language to let the programmer/user know that there is an unforseen process causing unexpected behavior.
In most programming language, when an exception is raised, the program stops and a message is sent back.
42 + 'answer' # => TypeError (String can't be coerced into Integer)
A lot of programming language provides a hierarchy of built-in classes to simplify the exception handling.
In Ruby, the very first exception class is the
Exception class, which has several subclasses, many of which also have descendents of their own.
Exception to Handle
Exceptions can and for some should be handled. In Ruby, the descendents of the
StandardError class are errors which are safe to handle. They are caused by circumstances such as unexpected user input, faulty type conversions or dividing by zero.
Some errors, however, must not be handled; doing so would be dangerous. Handling them would result in masking critical errors and can make debugging more difficult than it already is.
This include importants errors such as
How to Handle an Exceptional State
In Ruby, we use the
rescue block to handle errors. The block prevent your program from stopping if the specified exception is raised.
begin # do something dangerous here rescue TypeError # do something if TypeError is raised rescue ArgumentError # do something else if ArgumentError is raised end
When a issue is raised between
rescue, Ruby stops the execution of the code and goes straight to the
rescue block. In other words:
begin array.fetch(index) # The index is out of bonds puts "This code won't execute if out of bonds" rescue IndexError puts "Out of bonds!" end
In the code above, te
puts method call behind the
array.fetch line will not execute if
index is out of bonds; Ruby goes straight to
It is also possible to specify multiple exception on the same line in order to take the same action for more than one type of exception:
begin # do something dangerous here rescue ZeroDivisionError, TypeError # do something if ZeroDivisionError or TypeError are raised end
Useful Clauses in Ruby
There are several useful clause to use along the
rescue block. Let’s see some of them.
begin # do something dangerous here rescue # handle the inevitable exception ensure # do this every time, exception or not end
ensure is run whether an exception was raised or not. It’s useful to close file or connection with database, for example.
Another example is
retry: it lets you retry running your code after it raised an exception:
RETRY_LIMIT = 5 begin attempts = attempts || 0 # do something dangerous rescue attempts += 1 retry if attempts < RETRY_LIMIT end
This is useful when dealing with network connection and remote connection, where the line can sometime be busy.
Manually Raising Exceptions
It is possible to manually raises exception. In Ruby, it is done with the…
raise TypeError.new("Task failed successfully.")
Exceptions raised manually can, or course, be handled in the same manner as exceptions Ruby raises automatically.
Crate Custom Exceptions
Exceptions being classes, we can create our own custom exception classes, if we so wish.
class ValidateSomethingError < StandardError # validate something one way or anotehr end