Ruby Exception Handling Examples

Discover practical examples of Ruby exception handling to enhance your programming skills and error management.
By Jamie

Introduction to Ruby Exception Handling

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.

Example 1: Basic Exception Handling with 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.

Notes:

  • You can define multiple rescue clauses to handle different types of exceptions.
  • The error object e can be used to get more details about the error if needed.

Example 2: Ensuring Cleanup with 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.

Notes:

  • ensure is executed after the begin and rescue blocks, making it ideal for cleanup tasks.
  • Always check if the resource (like the file) is not nil before calling methods on it.

Example 3: Custom Exception Handling

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.

Notes:

  • Custom exceptions can help make your code more readable by providing more context about errors.
  • Use meaningful names for custom exceptions to clarify their purpose in the application.