Excepciones en Ruby
Qué son y cómo usarlas
Un día quise llevar a mis padres al cine, unos días antes me puse a planificar todo y a sacar cuentas, las cotufas, las bebidas, el día, la hora de a función, etc. Lo único que me faltaba era comprar las entradas, pero como íbamos un día que no va mucha gente,a me dije — las compro en taquilla — . Cuando llegamos al cine y me acerco a la taquilla, me informan que no quedan entradas para esa función, resulta que había un evento cerca y el cine llamó la atención, decidimos entonces posponer ir al cine y fuimos a cenar a un restaurante cerca.
Podríamos decir que tuve mala suerte o que pude haber hecho mil cosas diferentes para evitarlo, pero lo que quiero recalcar es que fue algo imprevisto, un suceso que no se tomó en cuenta, una excepción en nuestra planificación de ir al cine.
En Ruby también tenemos excepciones, algo que puede romper el comportamiento de nuestro código.
¿Que es una excepción?
Una excepción en Ruby es un objeto, una instancia ya sea de la clase Exception
o descendiente de esta, la presencia de una excepción indica que algo imprevisto ocurrió, comúnmente algo malo que no tomamos en cuenta.
Cuando se detecta una excepción, el programa se detiene y comienza a cerrarse, si nada detiene este proceso entonces terminaras con tu programa cerrado y un mensaje de error.
Por ejemplo si intentamos sumar '1' + 1
obtenemos una excepción de la clase TypeError
Que nuestro programa cierre inesperadamente por una excepción no es lo que queremos y nuestros usuarios tampoco.
Begin y rescue al rescate
Para manejar las excepciones y evitar que cierren nuestro programa podemos hacer uso de begin
y rescue
, son keywords en Ruby que nos permiten envolver nuestro pedazo de código en un bloque para actuar si ocurre una excepción.
begin
'1' + 1
rescue
solventar_el_error()
end
El comportamiento el similar a un if
y else
, cualquier excepción que se encuentre dentro de begin
activara la ejecución del código dentro de rescue
, de esta forma podemos notificar sobre el error de forma amigable o dependiendo del caso, resolver el error, si ninguna excepción es levantada dentro de begin
entonces el código dentro de rescue
no será ejecutado.
Pero tenemos un problema, sabemos que el error es de clase TypeError porque estamos creando la excepción adrede, pero en el mundo real no sera así, ¿como obtenemos que tipo de error es? o ¿cual es el mensaje de error?.
Objeto Exception
El objeto Exception
tiene toda la información del error ocurrido, se puede tener acceso a este objeto dentro del bloque de rescue
rescue => e
# Aqui se puede usar el objeto e (excepción)
e.class # nos da la clase de la excepción.
e.message # nos da el mensaje del error.
Con el ejemplo anterior podemos atajar todos los tipos de excepciones que ocurran en el bloque de begin
, si quisiéramos actuar diferente según el tipo de excepción podemos usar multiples rescue de la siguiente forma
rescue TypeError => e
e.class # => TypeError
rescue NameError => e
e.class # => TypeError
Podemos encadenar “rescues”, si el bloque de rescue
no maneja la excepción, entonces este le pasara la excepción a el siguiente bloque de rescue
.
Levantar una excepción
Podemos “levantar” nuestras propias excepciones con la keyword raise
, esto nos sirve para alertar cuando algo critico pasa en nuestro programa.
La manera mas simple de hacer esto es invocar a raise
y pasarle un string, este representara el mensaje del error, las excepciones levantadas de esta forma siempre serán de la clase RuntimeError
begin
raise 'Esto es un error custom.'
rescue => e
e.class # => RuntimeError
e.message # => Esto es un error custom.
end
También podemos usar clases de excepciones que ya están dentro de Ruby por defecto y usar un mensaje propio.
begin
raise TypeError, "TypeError con un mensaje custom."
rescue => e
e.class # => TypeError
e.message # => TypeError con un mensaje custom.
end
Las clases de excepciones
Todas las excepciones heredan de forma directa o indirecta de la clase Exception
, esta es la lista de todas las excepciones por default en ruby
Exception
NoMemoryError
ScriptError
LoadError
NotImplementedError
SyntaxError
SignalException
Interrupt
StandardError
ArgumentError
IOError
EOFError
IndexError
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError
SecurityError
SystemCallError
SystemStackError
ThreadError
TypeError
ZeroDivisionError
SystemExit
Aunque todas las excepciones heredan de Exception
no es buena idea usar esta clase para “rescatar” errores, ya que abarca errores que tu no quisieras rescatar, por ejemplo NoMemoryError
, la clase de excepciones que quisieras usar es StandardError
o alguna de sus clases hijas.
En este artículo aprendimos sobre las excepciones, que son y que representan en el mundo de Ruby, como manejar los errores actuando cuando uno aparezca y evitar que nuestro programa se cierre por completo.