In this article, we’re going to explore the following topics:

what’s an error in Ruby ?

how to throw & catch an error ?

errors & magic variables

Before to start

I’m thrilled to share with you our latest project: Fun Facts about Ruby — Volume 1

Please feel free to spread the word and share this post! 🙏

Thank you for your time!

What’s an error in Ruby ?

As Ruby is a fully object-oriented language, an error is an instance of a class that includes the Exception class in its ancestor chain

irb> RuntimeError.ancestors.include? Exception

=> true

irb> NoMethodError.ancestors.include? Exception

=> true

That’s why an error is commonly called an “exception” in Ruby.

NB: feel free to have a look to the Ruby Object Model: Part I article if you’re unfamiliar with the ancestor chain in Ruby.

As an error is a class, Ruby provides a bunch of instance methods to deal with an error.

These methods are defined in the Exception class and used by all of its children.

For example, the Exception#message method returns the message associated to the error when the Exception#backtrace method returns the error backtrace.

Feel free to browse the Exception official documentation for further information.

How to throw & catch an error ?

The Kernel#raise method is in charge of raising errors in Ruby

irb> raise 'an error occurred'

RuntimeError: an error occurred

irb> raise NoMethodError, 'an error occurred'

NoMethodError: an error occurred

In the first call to Kernel#raise , we can see that the method raises a RuntimeError — as no error class is explicitly specified as argument.

In contrary, in the second call to Kernel#raise , the raised exception is a NoMethodError — as we defined it as first argument of the method call.

These exceptions can be caught by a rescue clause within a begin...end block

produces

NoMethodError: an error occurred

Here, the rescue clause caught the NoMethodError exception raised by the call to the Kernel#raise method within the begin...end block.

The begin...end block is used to compartmentalize blocks of code depending on the possible errors that can occur for each of them

produces

ZeroDivisionError: divided by 0

NoMethodError: undefined method `odd?' for "my string":String

Note that in the first begin...end block, the 3 / 0 operation internally raised the ZeroDivisionError via the Integer#/ method.

Feel free to read the Numbers and Class Hierarchy in Ruby article if you are unfamiliar with the Integer class and its ancestor chain.

It’s same for the second begin...end block where the BasicObject#method_missing Ruby hook method raised the NoMethodError .

Feel free to read the Metaprogramming: Ruby Hook Methods article if you are unfamiliar with the hook methods in Ruby.

Errors & magic variables

Ruby provides 2 magic variables that are set when an exception is raised:

The $! variable that contains the raised exception

variable that contains the raised exception The $@ variable that contains the exception backtrace

produces

NoMethodError: undefined method `odd?' for "my string":String

/workspace.rb:87:in `eval'

/workspace.rb:87:in `evaluate'

...

/bin/irb:11:in `<main>'

These variables are cleared — set to nil — when the rescue block ends.

Voilà !

Feel free to have a look to the Part II.

May I have your attention please 🎤🎤

Feel free to subscribe here: www.rubycademy.com