Una excepción es un tipo especial de objeto de la clase Exception. Lanzar una excepción significa parar la ejecución de un programa para salir del mismo o para tratar con el problema que se ha producido. Para tratar el problema hace falta raise
; de no ser así, el programa termina y avisa del error. Lo que hará raise
(lanzar), será lanzar una "excepción" para manejar el error. Ruby tiene una serie de clases, Exception
y sus hijas, que ayudan a manejar los errores que pueden ocurrir.
def lanzar_excepcion
puts 'Estoy antes del raise'
raise 'Se ha producido un error' # lanza una excepción con el mensaje entre ''
puts 'Estoy despues del raise'
end
lanzar_excepcion
El método raise
procede del módulo Kernel
. Por defecto, raise
crea una excepción de la clase RuntimeError
. Para lanzar una excepción de una clase específica, se puede poner el nombre de la clase como argumento de raise
.
def inverse(x)
raise ArgumentError, 'El argumento no es numerico' unless x.is_a? Numeric
1.0 / x
end
puts inverse(2)
puts inverse('patata') # da un error que es manejado por raise
Hay que recordar que los métodos que actúan como preguntas, se les pone un ?
al final: is_a?
pregunta al objeto cuál es su tipo. Y unless cuando se pone al final de una instrucción, significa que NO se ejecuta cuando la expresión a continuación es verdadera.
Para tratar una excepción, se pone el método que puede causar el error dentro de un bloque begin…end
. Dentro de este bloque, se pueden poner varios rescue
para cada tipo de error que pueda surgir:
def raise_and_rescue
begin
puts 'Estoy antes del raise'
raise 'Un error ha ocurrido' # simulamos un error
puts 'Estoy después del raise'
rescue
puts 'Estoy rescatado del error.'
end
puts 'Estoy después del bloque'
end
raise_and_rescue
La salida es:
Estoy antes del raise
Estoy rescatado del error.
Estoy después del bloque
Observar que el código interrumpido por la excepción, nunca se ejecuta. Una vez que la excepción es manejada (por el rescue
), la ejecución continúa inmediatamente después del bloque begin
fuente del error.
Al escribir rescue
sin parámetros, el parámetro StandardError
se toma por defecto. En cada rescue se pueden poner varias excepciones a tratar. En el caso de poner múltiples rescues:
begin
#
rescue UnTipoDeExcepcion
#
rescue OtroTipoDeExcepcion
#
else
# Otras excepciones
end
Ruby compara la excepción que produce el error, con cada rescue hasta que sea del mismo tipo; o sea una superclase de la excepción. Si la excepción no concuerda con ningún rescue, usar else se encarga de manejarla.
Para saber acerca del tipo de excepción, hay que mapear el objeto Exception a una variable usando rescue:
begin
raise 'Test de excepcion'
rescue Exception => e
puts e.message # Test de excepción
puts e.backtrace.inspect # ["nombre de fichero:linea de la excepción"]
end
Si además de manejar la excepción, se necesita que se ejecute un código, se usará la instrucción ensure: lo que haya en ese bloque, siempre se ejecutará cuando el bloque begin…end
termine.
He aquí algunas excepciones más comunes, con la causa que las origina y un ejemplo:
RuntimeError
- la excepción que se lanza por defecto. Ejemplo:raise
NoMethodError
- el objeto no puede manejar el mensaje/método que se le envía. Ej:string = 'patata'
string.multiplicarse
NameError
- el intérprete encuentra un identificador que no puede resolver ni como método, ni como variable. Ej:a = variable_sin_definir
IOError
- lectura de un stream cerrado, escribir a un sistema de sólo lectura y operaciones parecidas. Ej:STDIN.puts("No escribas a STDIN!")
Errno::error - errores relaccionado con el fichero IO. Ej:
File.open(-12)
TypeError
- un método recibe un argumento que no puede manejar. Ej:a = 3 + "no puedo sumar un string a un número!"
ArgumentError
- causado por un número incorrecto de argumentos. Ej:def m(x)
end
m(1,2,3,4,5)
begin
# Abre el fichero y lo lee
File.open('origen.txt', 'r') do |f1|
while line = f1.gets
puts line
end
end
# Crea un nuevo fichero y escribe en él
File.open('destino.txt', 'w') do |f2|
f2.puts "Creado por Satish"
end
rescue Exception => msg
# dispone el mensaje de error
puts msg
end