Today its time to talk about exceptions. In real life we are usually pretty good at creating fail-safes for ourselves when interacting within our respective environments. We wear safety goggles when working in or around projectiles, we keep kleenex around for those times of the year when catching the sniffles are most prominent. Things like safety harnesses, tennis shoes and having auto-pay selected for a bill or series of bills are also considered to be safeguards.
An exception is sort of like a fail-safe within your computer program. An exception being a problem that arises during the execution of our program. Exception handling is the process of responding to the occurrence, similar to how auto-paying bills pre-handles the occurrence of the due dates of our recurring debts.
In Ruby an exception is an object of the Exception class that represents some type of exceptional condition, in other words, exceptions indicate that something went wrong. Ruby by default, terminates when an exception occurs, but its possible to declare exception handlers.
An exception handler is a block of code which is executed when an exception occurs during the execution of some other block of code. Raising an exception means stopping normal execution of the program and passing the control to the exception handling code. From here, two things can happen. As mentioned a little earlier, Ruby will by default terminate the program unless you provide whats known as a ‘rescue’ clause, to pass the control flow to.
Lets see an example:
The ‘begin’ and ‘end’ from the example above is the block that exceptions are housed in. The two rescue clauses instructs Ruby on the types of exceptions we want to handle. The ‘else’ conditional allows for one or more additional exceptions to be added, while ‘ensure’ guarantees its contents execution. ‘Ensure’ goes after the last rescue clause and contains a chunk of code that will always be executed as the block terminates.
All the code from ‘begin’ to the first ‘rescue’ in the above example would be protected. If an exception occurs during the execution of this block of code, control is passed to the block between ‘rescue’ and ‘end’. For each rescue clause inside of the begin block, Ruby compares the raised Exception against each of the parameters in turn. The match will succeed if the exception named in the rescue class is the same as the type of the currently thrown exception, or is a superclass of that exception.
Although the parameters to the rescue clause are typically the names of exception classes, they can be arbitrary expressions that return an Exception class
System errors are raised when a call to the operating system returns an error code. Ruby takes these errors and wraps each of them in a specific exception object. Each is a subclass of SystemCallError, and each is defined in a module called Errno.