Buscar..


Observaciones

Una excepción es un objeto que representa la ocurrencia de una condición excepcional. En otras palabras, indica que algo salió mal.

En Ruby, las excepciones a menudo se conocen como errores . Esto se debe a que la clase de Exception base existe como un elemento de objeto de excepción de nivel superior, pero las excepciones de ejecución definidas por el usuario generalmente son StandardError o descendientes.

Levantando una excepción

Para generar una excepción, use Kernel#raise pasando la clase de excepción y / o el mensaje:

raise StandardError # raises a StandardError.new
raise StandardError, "An error" # raises a StandardError.new("An error")

También puede simplemente pasar un mensaje de error. En este caso, el mensaje se envuelve en un RuntimeError :

raise "An error" # raises a RuntimeError.new("An error")

Aquí hay un ejemplo:

def hello(subject)
  raise ArgumentError, "`subject` is missing" if subject.to_s.empty?
  puts "Hello #{subject}"
end

hello # => ArgumentError: `subject` is missing
hello("Simone") # => "Hello Simone"

Creando un tipo de excepción personalizado

Una excepción personalizada es cualquier clase que amplíe Exception o una subclase de Exception .

En general, siempre debe extender StandardError o un descendiente. La familia de Exception suele ser por errores de máquinas virtuales o del sistema, al rescatarlos se puede evitar que una interrupción forzada funcione como se espera.

# Defines a new custom exception called FileNotFound
class FileNotFound < StandardError
end

def read_file(path)
  File.exist?(path) || raise(FileNotFound, "File #{path} not found")
  File.read(path)
end

read_file("missing.txt")  #=> raises FileNotFound.new("File `missing.txt` not found")
read_file("valid.txt")    #=> reads and returns the content of the file

Es común nombrar excepciones agregando el sufijo de Error al final:

  • ConnectionError
  • DontPanicError

Sin embargo, cuando el error se explica por sí mismo, no es necesario agregar el sufijo de Error porque sería redundante:

  • FileNotFound vs FileNotFoundError
  • DatabaseExploded vs DatabaseExplodedError

Manejando una excepción

Use el bloque de begin/rescue para capturar (rescatar) una excepción y manejarla:

begin
  # an execution that may fail
rescue
  # something to execute in case of failure
end

Una cláusula de rescue es análoga a un bloque catch en un lenguaje con llaves como C # o Java.

Un simple rescue como este rescata a StandardError .

Nota: tenga cuidado de evitar la captura de Exception lugar del StandardError predeterminado. La clase de Exception incluye SystemExit y NoMemoryError y otras excepciones serias que normalmente no desea capturar. Siempre considere capturar StandardError (el predeterminado) en su lugar.

También puede especificar la clase de excepción que debe ser rescatada:

begin
  # an excecution that may fail
rescue CustomError
  # something to execute in case of CustomError
  # or descendant
end

Esta cláusula de rescate no detectará ninguna excepción que no sea CustomError .

También puede almacenar la excepción en una variable específica:

begin
  # an excecution that may fail
rescue CustomError => error
  # error contains the exception
  puts error.message # provide human-readable details about what went wrong.
  puts error.backtrace.inspect # return an array of strings that represent the call stack
end

Si no pudo manejar una excepción, puede elevarla en cualquier momento en un bloque de rescate.

begin
   #here goes your code
rescue => e
    #failed to handle 
    raise e
end

Si desea reintentar su bloque de begin , llame a retry :

begin
   #here goes your code
rescue StandardError => e
   #for some reason you want to retry you code
   retry
end

Puede quedar atrapado en un bucle si detecta una excepción en cada reintento. Para evitar esto, limite su retry_count a un cierto número de intentos.

retry_count = 0
begin
      # an excecution that may fail
rescue
    if retry_count < 5
        retry_count = retry_count + 1
        retry
    else
        #retry limit exceeds, do something else
    end

También puede proporcionar un bloque else o un bloque ensure . Se ejecutará un bloque else cuando el bloque de begin se complete sin una excepción lanzada. Siempre se ejecutará un bloque de ensure . Un bloque de ensure es análogo a un bloque finally en un lenguaje de llaves como C # o Java.

begin
  # an execution that may fail
rescue
  # something to execute in case of failure
else
  # something to execute in case of success
ensure
  # something to always execute
end

Si se encuentra dentro de una def , module o bloque de class , no es necesario utilizar la instrucción begin.

def foo
    ...
rescue
    ...
end

Manejando múltiples excepciones

Puedes manejar múltiples errores en la misma declaración de rescue :

begin
  # an execution that may fail
rescue FirstError, SecondError => e
  # do something if a FirstError or SecondError occurs
end

También puede agregar múltiples declaraciones de rescue :

begin
  # an execution that may fail
rescue FirstError => e
  # do something if a FirstError occurs
rescue SecondError => e
  # do something if a SecondError occurs
rescue => e
  # do something if a StandardError occurs
end

El orden de los bloques de rescue es relevante: la primera coincidencia es la ejecutada. Por lo tanto, si coloca StandardError como la primera condición y todas sus excepciones heredan de StandardError , las otras declaraciones de rescue nunca se ejecutarán.

begin
  # an execution that may fail
rescue => e
  # this will swallow all the errors
rescue FirstError => e
  # do something if a FirstError occurs
rescue SecondError => e
  # do something if a SecondError occurs
end

Algunos bloques tienen un manejo de excepciones implícito como def , class y module . Estos bloques le permiten omitir la instrucción begin .

def foo
    ...
rescue CustomError
    ...
ensure
    ...
end

Agregando información a excepciones (personalizadas)

Puede ser útil incluir información adicional con una excepción, por ejemplo, para fines de registro o para permitir el manejo condicional cuando se detecta la excepción:

class CustomError < StandardError
  attr_reader :safe_to_retry

  def initialize(safe_to_retry = false, message = 'Something went wrong')
    @safe_to_retry = safe_to_retry
    super(message)
  end
end

Levantando la excepción:

raise CustomError.new(true)

Capturando la excepción y accediendo a la información adicional proporcionada:

begin
  # do stuff
rescue CustomError => e
  retry if e.safe_to_retry
end


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow