English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Excepciones en Ruby

Las excepciones y la ejecución siempre están relacionadas. Si abre un archivo inexistente y no maneja adecuadamente esta situación, su programa se considera de baja calidad.

Si ocurre una excepción, el programa se detiene. Las excepciones se utilizan para manejar varios tipos de errores, que pueden ocurrir durante la ejecución del programa, por lo que se deben tomar medidas adecuadas para evitar que el programa se detenga completamente.

Ruby ofrece un mecanismo perfecto para manejar excepciones. Podemos comienzo/fin En el bloque se adjunta el código que puede lanzar excepciones, y se utiliza rescue La cláusula indica el tipo de excepción que Ruby debe manejar perfectamente.

Sintaxis

begin #comienza
 
 raise.. #lanza una excepción
 
rescue [ExceptionType = StandardException] #captura la excepción del tipo especificado, el valor predeterminado es StandardException
 $! #indica la información de la excepción
 $@ #indica la ubicación del código donde se produjo la excepción
else #otras excepciones
 ..
ensure # Ingresar al bloque de código sin importar si hay o no excepciones
 
end # Finalizar

desde comienzo a rescue es protegido. Si se produce una excepción durante la ejecución del bloque de código, el control se transfiere a rescue lo que está en fin y

entre los bloques. comienzo para rescue cada

postcisos, Ruby compara la excepción lanzada con cada parámetro en turno. Si el tipo de excepción nombrado en el bloque 'rescue' coincide con el tipo de excepción actual o es una subclase de la excepción, se realiza una coincidencia exitosa. rescue Si la excepción no coincide con todos los tipos de errores especificados, podemos usar todos los else postciso.

Ejemplo en línea

#!/usr/bin/ruby
 
comienzo
   file = open("/unexistant_file)
   if file
      puts "File opened successfully"
   fin
rescue
      file = STDIN
fin
print file, "==", STDIN, "\n"

El resultado de ejecutar el ejemplo anterior es. Puedes ver que,STDIN reemplazó file porqueal abrirfalló.

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

usar retry instrucción

Puedes usar rescue El bloque captura la excepción y luego usa retry La sentencia comienza a ejecutarse desde el principio comienzo bloque.

Sintaxis

comienzo
    # La excepción lanzada por este código se capturará por el siguiente bloque 'rescue'
rescue
    # Este bloque capturará todos los tipos de excepciones
    retry # Esto llevará el control al inicio de 'begin'
fin

Ejemplo en línea

#!/usr/bin/ruby
 
comienzo
   file = open("/unexistant_file)
   if file
      puts "File opened successfully"
   fin
rescue
   fname = "existant_file"
   retry
fin

A continuación, se muestra el flujo de procesamiento:

  • Se produjo una excepción al abrir.

  • Salta a 'rescue'. 'fname' se reasigna.

  • Salta al inicio de 'begin' usando 'retry'.

  • Esta vez se abrió el archivo con éxito.

  • Continúa con el proceso básico.

Atención:Si el archivo renombrado no existe, el código de ejemplo en este ejemplo intentará infinitamente. Por lo tanto, usa con cautela la gestión de excepciones. retry.

usar raise instrucción

Puedes usar raise La sentencia lanza una excepción. El siguiente método lanza una excepción en el momento de la llamada. Su segundo mensaje se mostrará.

Sintaxis

raise 
 
o
 
raise "Error Message" 
 
o
 
raise ExceptionType, "Error Message"
 
o
 
raise ExceptionType, "Error Message" condition

La primera forma simplemente relanza la excepción actual (si no hay excepción actual, lanza un RuntimeError). Esto se utiliza en el administrador de excepciones que necesita explicar la excepción antes de pasarla.

La segunda forma crea una nueva RuntimeError Excepción, configura su mensaje con la cadena proporcionada. La excepción se lanza después de la pila de llamadas.

La tercera forma utiliza el primer parámetro para crear una excepción y luego configura el mensaje relevante como el segundo parámetro.

La cuarta forma es similar a la tercera, puede agregar cualquier condición adicional (por ejemplo}} unless)para lanzar una excepción.

Ejemplo en línea

#!/usr/bin/ruby
 
comienzo  
    puts 'Estoy antes del raise.'  
    raise 'Se ha producido un error.'  
    puts 'Estoy después del raise.'  
rescue  
    puts 'Estoy siendo rescate.'  
fin  
puts 'Estoy después del bloque begin.'

El resultado de salida del ejemplo anterior es:

Estoy antes del raise.  
Estoy siendo rescate.  
Estoy después del bloque begin.

Otro ejemplo raise Ejemplo de uso:

Ejemplo en línea

#!/usr/bin/ruby
 
comienzo  
  raise 'Una excepción de prueba.'  
rescue Exception => e  
  puts e.message  
  puts e.backtrace.inspect  
fin

El resultado de salida del ejemplo anterior es:

Una excepción de prueba.
["main.rb:4"]

usar asegurar instrucción

A veces, independientemente de si se lanza una excepción o no, es necesario garantizar que ciertos procesos se completen al finalizar el bloque de código. Por ejemplo, puede que abra un archivo al ingresar al bloque y necesite asegurarse de cerrarlo al salir del bloque.

asegurar Lo que hace la cláusula es esto. La cláusula ensure se coloca después del último rescate y contiene un bloque de código que siempre se ejecuta al finalizar el bloque. No importa si el bloque sale normalmente, si lanza y maneja una excepción, o si termina debido a una excepción no capturada,asegurar El bloque siempre se ejecuta.

Sintaxis

comienzo 
   #.. Proceso
   #.. Lanza excepción
rescue 
   #.. Maneja errores 
asegurar 
   #.. Asegura que se ejecute finalmente
   #.. Esto siempre se ejecuta
fin

Ejemplo en línea

comienzo
  raise 'Una excepción de prueba.'
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
asegurar
  puts "Asegurando ejecución"
fin

El resultado de salida del ejemplo anterior es:

Una excepción de prueba.
["main.rb:4"]
Asegurando ejecución

usar else instrucción

si se proporciona else cláusula, que generalmente se coloca en rescue Después de la cláusula, cualquier asegurar Antes.

else La parte principal de la cláusula solo se ejecuta cuando el cuerpo del código no lanza una excepción.

Sintaxis

comienzo 
   #.. Proceso 
   #.. Lanza excepción
rescue 
   #.. Maneja errores
else
   #.. Si no hay excepciones, ejecuta
asegurar 
   #.. Asegura que se ejecute finalmente
   #.. Esto siempre se ejecuta
fin

Ejemplo en línea

comienzo
 # Lanza una 'excepción de prueba'.
 puts "No estoy lanzando una excepción"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
else
   puts "¡Felicidades"-- ¡sin errores!"
asegurar
  puts "Asegurando ejecución"
fin

El resultado de salida del ejemplo anterior es:

No estoy lanzando una excepción
¡Felicidades!-- ¡sin errores!
Asegurando ejecución

Se puede capturar el mensaje de error lanzado utilizando la variable $!

Catch y Throw

El mecanismo de excepciones raise y rescue puede abandonar la ejecución en caso de error, a veces es necesario saltar algunas estructuras de anidación profunda en el procesamiento normal. En estos casos, catch y throw son muy útiles.

catch Se define un bloque que utiliza un nombre dado (puede ser un Symbol o String) como etiqueta. El bloque se ejecutará normalmente hasta que se encuentre un throw.

Sintaxis

throw :lablename
#.. Esto no se ejecutará
catch :lablename do
#.. Se ejecutará después de encontrar un throw
fin
 
o
 
throw :lablename condition
#.. Esto no se ejecutará
catch :lablename do
#.. Se ejecutará después de encontrar un throw
fin

Ejemplo en línea

En el siguiente ejemplo, si el usuario ingresa '!' como respuesta a cualquier solicitud, se utiliza un throw para finalizar la interacción con el usuario.

Ejemplo en línea

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   throw :quitRequested if res == "!"
   return res
fin
 
catch :quitRequested do
   nombre = promptAndGet("Nombre: ")
   edad = promptAndGet("Edad: ")
   sexo = promptAndGet("Sexo: ")
   # ..
   # Procesar información
fin
promptAndGet("Nombre:")

El programa anterior requiere interacción manual, puede probarlo en su computadora. Los resultados de ejecución de los ejemplos anteriores son los siguientes:

Nombre: Ruby on Rails
Edad: 3
Sexo: ¡
Nombre: Just Ruby

Clase Exception

Las clases y módulos estándar de Ruby lanzan excepciones. Todas las clases de excepción forman una jerarquía, incluyendo la clase Exception en la cima. La siguiente capa consta de siete tipos diferentes:

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal es otra excepción en esta capa, pero el intérprete de Ruby solo lo utiliza internamente.

ScriptError y StandardError tienen algunas subclases, pero aquí no necesitamos conocer estos detalles. Lo más importante es crear nuestra propia clase de excepción, que debe ser una subclase de Exception o de alguna de sus subclases.

Veamos un ejemplo:

Ejemplo en línea

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   fin
fin

Ahora, veamos el siguiente ejemplo, que utiliza la excepción anterior:

Ejemplo en línea

File.open(path, "w") do |file|
comienzo
    # Escribir datos ...
rescue
    # Error producido
    raise FileSaveError.new($!)
fin
fin

En este caso, la línea más importante es raise FileSaveError.new($!)Llamamos a raise para indicar que se ha producido una excepción, y se la pasamos a un nuevo ejemplo de FileSaveError, ya que el fallo de escritura de datos se debe a una excepción específica.