Ruby Exceptions Handling
Overview
Ruby exception handling is the process of dealing with the errors that can be raised in a program. Errors are unanticipated events that can occur while a program is running, which disrupt the normal flow of the program. Ruby exception handling mechanism helps to deal with bugs and any unforeseen circumstances in our programs. It addresses runtime issues like divide-by-zero, out-of-bounds, and file-not-found errors. In this article, we will explore the concept of Ruby Exception Handling and how it can help developers write more reliable and maintainable code.
What is Exception Handling in Ruby?
Ruby exception handling is the process of handling unexpected or undesirable occurrences while a program is executing. Ruby exception handling deals with these occurrences to prevent the program or system from crashing, and exceptions would disturb a program's regular execution if this procedure did not exist.
What is an Exception?
If any event occurs in the system that is unexpected or unwanted then it is known as an exception. The exception may disrupt the program or crash the system and stop the execution of the program.
In the above example, an unexpected situation arises when the program tries to divide a number by zero. This raises an exception causing the program execution to stop. So the print statement after the function call does not get executed.
How to Handle the Exceptions in Ruby?
In Ruby, exceptions can be handled using a set of statements. This feature grants developers the power to catch and manage exceptions, to make sure that system doesn't crash and program execution continues still after the exception has occurred.
In this example, we use Ruby exception handling to handle the ZeroDivisionError exception. Here, the statement after the function call also gets executed.
Errors Vs Exceptions
In Ruby, errors and exceptions are often used interchangeably, but there is a subtle difference between the two.
- Errors are usually caused by a programming mistake or a problem that cannot be handled at runtime.
- Exceptions, on the other hand, are situations that lie outside the program's scope of handling. For example, opening a non-existent file, accessing an undefined variable, or dividing by zero are some situations where exceptions can occur. When a program encounters such unexpected situations, its execution will stop but it can be handled using exception handling.
Exception Class
All exceptions in Ruby are instances of a class that inherits from the Exception class. The Exception class has a collection of methods for retrieving information about the exception, such as the message, backtrace, and exception class.
Some of the common methods are:
- exception - The exception method produces and returns a new exception object. Syntax
When called on an exception class, such as ZeroDivisionError, it creates a new object of that class with an optional message argument. Here is an example:
-
backtrace - This function returns any backtrace information associated with the exception object etc. Syntax
etc. backtrace -
Inspect - This method returns the class name and message of the exception. Syntax
etc. inspect
Exception Objects
An exception object is an instance of a class that represents the specific type of exception that has been raised. It holds information about the exception such as the kind of exception, the error message, and the backtrace. The exception object is provided to the exception handler, which then decides how to handle the exception.
Let's take a look at the following example
Output
In this example, we divide a number by zero which is illegal and will raise a ZeroDivisionError. If an exception is raised, control is moved to the rescue block. The exception objects get assigned to the variable ex. Inside the rescue block, we use the message method of the exec object to get the error message associated with the exception.
Statements Used in Exceptions
Ruby provides a set of statements that can be used to handle exceptions in a program. These are:
- Retry Statement
- Raise Statement
- Ensure Statement
- Else Statement
Retry Statement
The retry statement allows the program to retry an operation that has failed. The retry statement can be used in a rescue block to retry an operation that has raised an exception.
Syntax
Example
Output
Explanation
In the above example, we have used the raise method to manually create an exception. The control of the program enters the beginning block and then faces the exception. So the control then moves to the rescue block where it executes the statement and then the control goes back to the start of begin block. Again it faces an exception and control goes to the rescue block. This creates an infinite loop and thus the print statement gets executed infinite times. The rest of the begin block after the exception statement is never executed.
Raise Statement
The raise statement allows the program to explicitly raise an exception. The raise statement can be used to signal an error condition or to re-raise an exception that was caught by a rescue block.
Syntax
Example
Output
Explanation
In the example above, we call the divide method with the parameters 1 and 0. The divide method checks if the y parameter is 0. If the y parameter is 0, the program raises a ZeroDivisionError exception with the message "Division by 0 not possible" by executing the raise statement. If the y parameter is not 0, the program performs the division and returns the result.
Ensure Statement
The ensure statement allows the program to ensure that a block of code is executed, whether an exception is raised or not. This block always outputs something. It is put on top of the rescue block. The ensuring statement can be used to release resources, close files, or clean up after an operation.
Syntax
Example
Output
Explanation
In the example above, we raise an exception using the raise method. The control of code then moves to the rescue block which gets executed. Then, the control goes to the ensure block. Even if there was no exception raised in the beginning block, the ensure block would have been still executed. The ensure block gets executed irrespective of whether an exception is raised or not.
Else Statement
The else statement allows the program to specify code that is executed when no exception is raised in a begin block. The else statement can be used to handle the normal flow of execution and to separate error-handling code from normal code. It is present in between the rescue block and ensures block. The control of code can either enter the rescue block or the else block and not both.
Syntax
Example
Output
Explanation
In the above example. we are not raising any exceptions. So the code control enters the else block instead of the rescue block. The else block is executed and lastly, the ensure block gets executed.
Ruby Exception Handling: Catch and Throw
The catch-and-throw statements provide a way to exit from nested loops or method calls. The catch statement defines a block of code that can be exited by executing the throw statement.
Syntax
Example
Input and Output
The program inputs a two-dimensional array and a target value. The program outputs the target value if it is found in the array and nil otherwise.
Input 1
Output 1
Input 2
Output 2
Explanation
The search_array method in the above example looks for a target value in a two-dimensional array. The catch statement defines a block of code that can be exited by executing the throw statement. If the target value is located, the program performs the throw statement with the :target_found symbol and the target value as arguments. The catch block catches the :target_found symbol and returns the target value. The program returns nil in the absence of the desired value.
Frequently Asked Questions
Q: State the difference between an error and an exception in Ruby?
A: Errors are usually caused by a programming mistake or a problem that cannot be handled at runtime. Exceptions, on the other hand, are situations that are unexpected occurring when a program is executed.
Q: What is the difference between rescue and ensure in Ruby?
A: The rescue statement is used to catch and handle exceptions that are raised in a beginning block. The ensure statement is used to ensure that a block of code is executed, whether an exception is raised or not.
Q: How can I handle multiple types of exceptions in Ruby?
A: You can use multiple rescue blocks to handle different types of exceptions. The rescue blocks are evaluated in order, and the first block that matches the exception type is executed. You can also use the rescue modifier to handle multiple types of exceptions in a single line of code.
Q: Can I define my exception class in Ruby?
A: By subclassing the Exception class or one of its subclasses, you can define your exception class.
Conclusion
- Ruby exception handling is a critical part of writing robust and reliable code in Ruby.
- The rescue, assure, raise, retry, catch, and throw statements are some of the many techniques available for Ruby exception handling.
- Effective Ruby code writing requires an understanding of the distinctions between errors and exceptions as well as the correct way to handle each.
- It's crucial to employ the proper Ruby exception handling statements and the correct exception class for a specific circumstance.
- By using Ruby exception handling effectively, you can make your code more resilient and easier to maintain.