3 m read

Exception Handling in Ruby

Exception handling is a crucial process in any programming language. Ruby provides a way to predict and handle potential errors during the execution of program code without allowing the complete application to crash.

It’s all about managing error conditions and making sure your program can continue the run, even when things go wrong. In its simplest form, exception handling in Ruby works by using the “rescue” keyword.

Basics of Exception Handling

Understanding Begin-Rescue

At the bedrock of exception handling in Ruby is the begin-rescue clause. The section of your code that might raise an exception is enclosed in a begin block. If an exception occurs within this block, instead of halting the program, control is passed to the matching rescue clause.


begin
 x = 10 / 0
rescue ZeroDivisionError
 puts "You tried to divide by zero"
end
Code language: JavaScript (javascript)

In the above example, when Ruby tries to execute x = 10 / 0, it raises a ZeroDivisionError exception. Instead of crashing the program, Ruby directs the flow to the rescue block.

Specific Error Handling

Sometimes, different types of exceptions require different responses. This can be accomplished by using multiple rescue clauses, each handling a specific type of exception.


begin
 file = File.open("no-exist-file.txt")
rescue Errno::ENOENT
 puts "File not found!"
rescue
 puts "Some other error occurred"
end
Code language: PHP (php)

In this code snippet, if the file doesn’t exist, a specific exception Errno::ENOENT is raised and handled. If any other type of exception happens, the generic rescue handles it.

‘Ensure’ for Guaranteed Execution

Sometimes you might want to make sure some perform some operations regardless of an exception. The ensure keyword comes in handy for this scenario. Code within the ensure block will execute whether an exception was raised, rescued, or not.


begin
 file = File.open("any-file.txt")
rescue Errno::ENOENT
 puts "File not found!"
else
 puts "File opened successfully"
ensure
 file.close if file
end
Code language: PHP (php)

In the example above, regardless of the outcome (whether the file opens, doesn’t exist, or triggers an error), the file will be closed if it exists.

Advanced Concepts in Exception Handling

Using ‘Raise’ To Trigger Exceptions

Sometimes, we need to raise an exception ourselves. This could be due to a condition that the program regards as unacceptable. To raise your own exception, you use the raise method.


begin
 input = -1
 if input < 0
   raise "Input should be a positive number"
 end
rescue RuntimeError
 puts "An error occurred"
end
Code language: JavaScript (javascript)

In this example, we’re raising a RuntimeError exception when the input is less than 0. This error is then caught in the rescue block where it outputs “An error occurred”.

Understanding Catch and Throw

While begin-rescue is great for exception handling, another useful but less-known method is the catch-throw mechanism. Initially, this might seem to function similarly to a begin-rescue block, but it’s intended for situations when you need to break out of a nested structure like nested loops or methods, not exception handling.

Sensible Exception Handling Practices

Don’t Rescue Every Exception

It might be tempting to try rescuing all exceptions that might occur in a program. However, it’s generally best to only rescue exceptions that you know how to handle. Unhandled exceptions will provide meaningful error messages that can help diagnose and fix the issue.

Meaningful Responses

The purpose of rescuing exceptions is to handle them in a meaningful way. This may mean rerouting the program flow, logging the error for later review, or offering a solution to the user. Try to always take meaningful action in response to an exception.

Beware of Silent Failures

If an error occurs but our program rescues it and silently continues working, it might create elusive bugs. It’s good practice to log all caught exceptions, so you’re aware of any issues.

Conclusion

Handling exceptions smartly and effectively is crucial for writing reliable and sturdy Ruby programs. Ruby gives us powerful tools—begin-rescue blocks, raise, catch, and throw—to manage such unexpected conditions.

This article is a successor to the previous article on Ruby File Input and Output. Keep an eye out for our next articles in this series!

Post your comments and questions below, and stay tuned for our upcoming tutorials. Happy Coding!

Benji

Leave a Reply