The Exception class is the root class of all exceptions in Ruby. It holds the type of exception (usually in the type of the exception object itself), an optional message as well as backtrace information. Beyond simply catching them, there are a few things that can be done with them.
Exceptions are usually created by calling the SomeExceptionClass.new method. I say SomeExceptionClass instead of merely Exception because it is idiomatic Ruby to subclass exception, you don't typically create Exception objects as they are difficult to catch in any meaningful way. So to create an exception, you must first make a child class with a descriptive name. Classes generally have names that describe the error or exceptional condition they represent, any particular class or task may have several or a whole hierarchy of these classes. Since they typically don't need to extend the base Exception class' functionality in any way, they're often simple, single-line statements.
class TestError < Exception; end
Now that you have a descriptive exception class, a new exception is created using the TestError.new("Some string describing the exceptional condition") method. This is typically fed directly to the raise keyword.
raise TestError.new("Testing the TestError class.")
An exception can be caught using a begin...rescue statement, like so.
begin raise TestError("Testing") rescue TestError => e # Get information from e and either retry, or bail end
But once you have one, what can you do with it? First off, read its message. This is done with the message method. It should return a simple string. But be aware, not all exceptions are created with messages. It depends on the scope and range of conditions that can create the exception. If an exception can only happen in very specific conditions, there's not much need to tell the programmer more about it.
begin raise TestError("Testing") rescue TestError => e puts e.message end
Where did this error occur? To see, examine the backtrace. The backtrace method returns an array of strings determining which line the backtrace went through. The very first line will be the line that generated the error. Each string is in the format of file:line:method or file:line.
begin raise TestError("Testing") rescue TestError => e puts e.backtrace.first end
Ruby comes with a library of standard exceptions, all descending from the StandardError class.
- ArgumentError - A specified number of arguments was expected, but not enough or too many were given.
- IndexError - An index operation failed, such as indexing past the end of an array.
- IOError - This one can be a bit more vague, as it represents errors possibly caused by external elements. An IOError can be raised when there is any problem with an IO object, such as failing to open a file, a network connection failing, trying to write to a read-only file, etc.
- LocalJumpError - Perhaps a bit of a misnomer this one, this is raised when you have tried to yield a value to a block or proc, but no block or proc was given.
- NameError - A very common one, this is raised when you try to call a method that isn't there.
- RegexpError - An error with a regular expression, usually when compiling the regular expression. See the error message for more useful information, since regular expressions are a language unto themselves, this can represent all manner of errors.
- RuntimeError - The default when a simple string is passed to the raise keyword. A variety of things raise RuntimeErrors.
- SecurityError - This is raised when you try to do something not allowed in your $SAFE level.
- SystemCallError - System calls are how Ruby talks to your operating system. A system call does simple things like allocate OS resources (memory, sockets, etc) or open files. If a system call fails, a SystemCallError is raised.
- SystemStackError - This is raised if there is a stack overflow. This usually means you have an infinite loop gone awry, or a recursive method is recursing too deeply.
- ThreadError - This is done when you try to perform an illegal operation on a thread, like trying to join a thread that hasn't yet been run.
- TypeError - Another vague exception type, this is raised when one type was expected, but another was received.
- ZeroDivisionError - Raised if you try to divide by zero.