Ruby has a robust error handling mechanism called rescue
. The way it works is the keyword rescue
specifies an exception handler that will catch and handle any exceptions that are raised in the begin
block, the code block preceding the rescue
block that may cause an exception.
Here’s how it looks:
begin
# code that may raise an exception
rescue
# code to handle the exception
end
When an exception occurs in the begin
code block, Ruby transfers control to the rescue
block and executes the code within it. And when no exception is raised, the rescue
block is skipped and the program continues executing normally.
Example: Using Rescue to Handle An Exception
In this example, the divide
method takes two arguments, a
and b
, and attempts to divide a
by b
. If b
is zero, a ZeroDivisionError
exception is raised. To handle this exception, we use a begin
block followed by a rescue
block. The rescue
block catches the ZeroDivisionError
exception and prints an error message to the console. It then sets the result to nil
and returns it.
def divide(a, b)
begin
result = a / b
rescue ZeroDivisionError => e
puts "Error: #{e.message}"
result = nil
end
return result
end
puts divide(10, 2) # Output: 5
puts divide(10, 0) # Output: Error: divided by 0
# nil
Output:
5
Error: divided by 0
The code block that might raise an exception is placed within the begin
block, and the rescue
block is used to handle the exceptions raised in the begin
block.
Common Methods of Handling Exceptions in Ruby
The rescue
keyword can be used in different ways to handle exceptions in Ruby. Let's look at some of the most common ways:
1. Handling a Specific Exception
If we want to handle a specific exception, we can specify the type of exception we want to handle in the rescue block.
begin
# code that may raise a ZeroDivisionError exception
rescue ZeroDivisionError
# code to handle the ZeroDivisionError exception
end
In the above code, the rescue block will only catch ZeroDivisionError
; if any other exception is raised, it will not be caught by this block.
2. Handling Multiple Exceptions
We can also handle numerous exceptions in a single rescue block by separating them with commas.
begin
# code that may raise an exception
rescue ZeroDivisionError, TypeError
# code to handle the ZeroDivisionError or TypeError exception
end
The rescue block in the preceding code will only catch ZeroDivisionError
and TypeError
; any other exception raised will not be caught by this block.
3. Handling All The Exceptions
Now this is an interesting point. All the exceptions and errors fall under the Exception
class, but rescuing the Exception
class will rescue every exception, and this might cause some problems, for instance:
SignalException::Interrupt
: If we rescue this, we can't exit our app by hitting ctrl+c.NoMemoryError:
Raised when our program keeps running after consuming all the RAM.
begin
#code that may raise an exception
rescue Exception => e
# This will swallow every single exception including system level exceptions. Nothing gets past it.
end
It's not a good practice to rescue system-level exceptions such as those above. We only want to catch all the application-level errors that our code raises, and all the exceptions that we should care about inherit from the StandardError
class.
The StandardError
class is the parent class of all the standard
error classes in Ruby, so it will catch any exception that is derived from it:
begin
# code that may raise an exception
rescue StandardError
# code to handle any exception
end
4. Using An Else Block
We can also use an else
block in our code, just after the rescue
block, to specify the code that should be executed if no exception is raised. In this example, the else
block will be executed if no exception is raised in the begin
block.
begin
# code that may raise an exception
rescue StandardError
# code to handle any exception
else
# code to execute if no exception is raised
end
In conclusion, the rescue
keyword is an essential part of Ruby's exception handling mechanism. It allows developers to gracefully handle exceptions and recover from errors, preventing unexpected program crashes. By understanding how to use rescue
to handle specific types of exceptions, multiple exceptions, or all exceptions, you can write more robust and reliable Ruby code.
At the same time, when using rescue
, it's important to carefully consider which exceptions to handle and how to handle them. Catching and handling every exception indiscriminately can lead to errors being masked and difficult to diagnose. It's also a good practice to make sure that any code in your rescue block is well-tested and doesn't introduce new bugs.
Track, Analyze and Manage Errors With Rollbar
Ruby provides a rich set of tools for developing and debugging code, but errors can still occur during development or execution. Being able to track, analyze, and manage errors in real-time can help you proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Ruby errors easier than ever. Try it today!