Ruby provides a robust mechanism for handling errors through exception handling. This ensures that your program can gracefully manage unexpected situations without crashing. Exception handling in Ruby is primarily done using begin
, rescue
, and ensure
blocks. Here are three practical examples that illustrate how to effectively handle exceptions in Ruby.
begin
and rescue
In this example, we will demonstrate how to catch and handle a basic division error when attempting to divide by zero. This is a common scenario that can occur in any program involving calculations.
When you try to perform a division operation, and the denominator is zero, Ruby raises a ZeroDivisionError
. Using the begin
and rescue
keywords, we can catch this error and handle it gracefully, allowing the program to continue running without crashing.
begin
result = 10 / 0
puts "The result is #{result}"
rescue ZeroDivisionError => e
puts "Error: You cannot divide by zero!"
end
In this code snippet, if the division succeeds, it prints the result. However, if a ZeroDivisionError
occurs, it rescues the error and outputs an informative message instead.
rescue
clauses to handle different types of exceptions.e
can be used to get more details about the error if needed.ensure
The ensure
block in Ruby is used to execute code regardless of whether an exception occurred or not. This is particularly useful for resource management, such as closing files or network connections.
In the following example, we will open a file for reading and ensure that it gets closed after processing, regardless of whether an error occurs during reading.
begin
file = File.open('example.txt', 'r')
content = file.read
puts content
rescue Errno::ENOENT => e
puts "Error: The file does not exist!"
ensure
file.close if file
puts "File has been closed."
end
Here, if the file does not exist, a Errno::ENOENT
exception is raised, and the rescue block handles the error. The ensure
block ensures that the file is closed properly, preventing memory leaks or file access issues.
ensure
is executed after the begin
and rescue
blocks, making it ideal for cleanup tasks.nil
before calling methods on it.Ruby allows you to define custom exceptions by creating a new class that inherits from StandardError
. This can be particularly useful when you want to differentiate between different types of errors in your application.
In this example, we’ll create a custom exception called InvalidInputError
and raise it when invalid data is encountered.
class InvalidInputError < StandardError; end
def process_input(input)
raise InvalidInputError, "Input must be a positive integer" unless input.is_a?(Integer) && input > 0
puts "Processing #{input}..."
end
begin
process_input(-5)
rescue InvalidInputError => e
puts "Error: #{e.message}"
end
In this code, the process_input
method checks if the input is a positive integer. If not, it raises an InvalidInputError
. The rescue block catches this custom exception, allowing for specific handling of invalid inputs.