Volver a la página principal
lunes 22 julio 2024
9

Cómo gestionar excepciones en Ruby

Conceptos Básicos de Excepciones

¿Qué es una Excepción?

Una excepción es un evento que ocurre durante la ejecución de un programa y que interrumpe el flujo normal de las instrucciones. En Ruby, las excepciones se representan mediante objetos de la clase Exception y sus subclases. Cuando ocurre una excepción, Ruby crea un objeto de excepción y lo lanza, lo que se denomina "raising an exception".

Lanzamiento de Excepciones

En Ruby, puedes lanzar una excepción utilizando el método raise. Aquí hay un ejemplo simple:

def divide(a, b)
  raise "Division by zero error" if b == 0
  a / b
end

begin
  divide(10, 0)
rescue => e
  puts "An error occurred: #{e.message}"
end

En este ejemplo, la división por cero lanza una excepción con el mensaje "Division by zero error". El bloque begin...rescue se utiliza para capturar y manejar la excepción.

Captura y Manejo de Excepciones

Bloques begin...rescue

El bloque begin...rescue es la estructura básica para manejar excepciones en Ruby. Aquí tienes un ejemplo básico:

begin
  # Código que puede lanzar una excepción
rescue StandardError => e
  # Código para manejar la excepción
  puts "An error occurred: #{e.message}"
end

En este ejemplo, cualquier excepción que se lance dentro del bloque begin y que sea una subclase de StandardError será capturada por el bloque rescue.

Cláusula else

Ruby permite agregar una cláusula else que se ejecutará si no ocurre ninguna excepción:

begin
  # Código que puede lanzar una excepción
rescue StandardError => e
  # Código para manejar la excepción
  puts "An error occurred: #{e.message}"
else
  # Código que se ejecuta si no ocurre ninguna excepción
  puts "No errors occurred."
end

Cláusula ensure

La cláusula ensure se utiliza para especificar el código que debe ejecutarse sin importar si ocurre una excepción o no. Esto es útil para liberar recursos, cerrar archivos, etc.

begin
  # Código que puede lanzar una excepción
rescue StandardError => e
  # Código para manejar la excepción
  puts "An error occurred: #{e.message}"
ensure
  # Código que siempre se ejecuta
  puts "This code always runs."
end

Captura de Excepciones Específicas

Puedes capturar excepciones específicas proporcionando el nombre de la clase de la excepción:

begin
  # Código que puede lanzar una excepción
rescue ZeroDivisionError => e
  # Manejo específico para la división por cero
  puts "Cannot divide by zero: #{e.message}"
rescue ArgumentError => e
  # Manejo específico para argumentos inválidos
  puts "Invalid argument: #{e.message}"
end

Definición de Nuevas Excepciones

En Ruby, puedes definir tus propias clases de excepción heredando de la clase StandardError o cualquier otra subclase de Exception.

class MyCustomError < StandardError; end

def risky_method
  raise MyCustomError, "Something went wrong"
end

begin
  risky_method
rescue MyCustomError => e
  puts "Caught a custom error: #{e.message}"
end

Retries y Rethrows

Retrying

En Ruby, puedes reintentar un bloque de código después de capturar una excepción utilizando la palabra clave retry.

attempts = 0

begin
  attempts += 1
  puts "Trying to do something..."
  raise "Temporary failure" if attempts < 3
  puts "Success on attempt #{attempts}"
rescue
  puts "An error occurred, retrying..."
  retry if attempts < 3
end

Rethrowing

A veces, después de capturar una excepción, es posible que desees relanzarla para que sea manejada en un nivel superior.

def risky_method
  raise "An error occurred"
end

begin
  begin
    risky_method
  rescue => e
    puts "Caught an error: #{e.message}"
    raise # Rethrowing the exception
  end
rescue => e
  puts "Handled rethrown error: #{e.message}"
end

Mejores Prácticas para Manejar Excepciones

1. No Capturar Excepciones Genéricas: Captura excepciones específicas para no atrapar inadvertidamente errores que no esperabas.

2. Manejo Adecuado de Recursos: Utiliza la cláusula ensure para liberar recursos, cerrar archivos o realizar cualquier limpieza necesaria.

3. Proporcionar Información Útil: Asegúrate de que los mensajes de las excepciones sean claros y proporcionen suficiente información para entender el problema.

4. Evitar el Uso Excesivo de Excepciones: Utiliza excepciones para condiciones verdaderamente excepcionales. No utilices excepciones para el flujo normal del programa.

5. Documentar las Excepciones: Documenta las excepciones que tus métodos pueden lanzar y cómo deben ser manejadas.

Ejemplo Completo

Para finalizar, aquí tienes un ejemplo completo que ilustra varios conceptos discutidos:

class CustomError < StandardError; end

def process_file(filename)
  raise CustomError, "File not found" unless File.exist?(filename)
  
  file = File.open(filename, "r")
  data = file.read
  puts data
rescue CustomError => e
  puts "Custom error: #{e.message}"
rescue StandardError => e
  puts "Standard error: #{e.message}"
ensure
  file.close if file
  puts "File closed"
end

begin
  process_file("non_existent_file.txt")
rescue => e
  puts "An error occurred in the main program: #{e.message}"
end

Este ejemplo define una excepción personalizada CustomError, la lanza si el archivo no existe, maneja diferentes tipos de excepciones y garantiza que el archivo se cierra correctamente utilizando la cláusula ensure.

La gestión de excepciones en Ruby es una herramienta poderosa para escribir programas robustos y resilientes. Al comprender y aplicar estas técnicas, puedes manejar errores de manera efectiva, asegurando que tu código sea más confiable y mantenible.

Etiquetas:
ruby
Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer