Un programmeur rencontre bon nombre de problème, souvent parce que son code contient des erreurs. Surtout lorsqu’on débute… C’est donc pratique de savoir où et pourquoi ces erreurs surviennent! On va donc baliser le parcours en gérant les exceptions.

Gérer une exception

Une exception, c’est une erreur du programme. Par exemple, si vous appelez une méthode qui n’existe pas :

def ma_methode
  mon_texte = "All your base are belong to us."
  mon_texte.methode_bizarre
end
ma_methode
→ in `ma_methode': undefined method `methode_bizarre' for "All your base are belong to us.":String (NoMethodError)

Le texte d’erreur est long et pas très gentil. On va changer ça :

def ma_methode
  mon_texte = "All your base are belong to us."
  mon_texte.methode_bizarre
  rescue Exception:
  puts "T'es vraiment mauvais en Ruby."
end
ma_methode
→ T'es vraiment mauvais en Ruby.

Là, c’est beaucoup plus personnalisé et sincère. Pour faire ça, j’ai rajouté le mot rescue suivant de l’élément auquel s’applique le code de la ligne suivante. Donc ici, avec le mot Exception: je gère toutes les exceptions, sans distinctions.

Si on veut un code perso lorsqu’on appelle une méthode inexistante :

def ma_methode
  mon_texte = "All your base are belong to us."
  mon_texte.methode_bizarre
  rescue NoMethodError:
  puts "T'appelles une méthode inexistante, imbécile."
  rescue Exception:
  puts "T'es vraiment mauvais en Ruby."
end
ma_methode
→ T'appelles une méthode inexistante, imbécile.

Ici, on a une phrase lorsqu’on appelle une méthode qui n’existe pas, et une méthode pour les autres exceptions. Ruby gères les blocs rescue dans l’ordre, donc si l’on met le bloc Exception avant le bloc NoMethodError, c’est le bloc Exception qui aurait été exécuté.

Exception avec variable

On peut envoyer le contenu de l’exception dans une variable, pour l’afficher par exemple.

def ma_methode
  mon_texte = "All your base are belong to us."
  mon_texte.methode_bizarre
  rescue NoMethodError => ma_var:
  puts "Voilà ton erreur imbécile : " + ma_var.to_s + "."
  rescue Exception:
  puts "T'es vraiment mauvais en Ruby."
end
ma_methode
→ Voilà ton erreur imbécile : undefined method `methode_bizarre' for "All your base are belong to us.":String.

Quand il n’y a pas d’erreur

Si votre code est nickel, on peut quand même afficher quelque chose :

def ma_methode
  mon_texte = "All your base are belong to us."
  rescue Exception:
  puts "T'es vraiment mauvais en Ruby."
  else
  puts "Zen attitude."
end
ma_methode
→ Zen attitude.

J’ai enlevé la ligne qui posait problème et ici, ma méthode marche parfaitement (même si elle ne fait rien de spécial). En conséquence, puisqu’aucune erreur n’a été rencontrée, j’affiche “Zen attitude.” Gratifiant, n’est-ce pas ?

ensure : assurer l’exécution d’un code

Avec ensure, on peut faire en sorte d’exécuter un code même si il y a des erreurs.

def ma_methode
  mon_texte = "All your base are belong to us."
  mon_texte.methode_bizarre
  rescue Exception:
  puts "T'es vraiment mauvais en Ruby."
  else
  puts "Zen attitude."
  ensure
  puts "En tout cas, tu fais des efforts."
end
ma_methode
→ T'es vraiment mauvais en Ruby.
En tout cas, tu fais des efforts.

Si le code est ok ou non, la phrase “En tout cas, tu fais des efforts.” s’affiche. Encourageant! En tout cas, ça permet par exemple d’être sûr de fermer des connexions ouvertes ou d’effacer des fichiers indésirables.

Essaie encore

Il y a aussi un moyen de rééxécuter le bloc de code si on rencontre une erreur, en utilisant le mot retry. J’ai pas réussi à faire un exemple convaincant (je bouclais des erreurs…) donc je ne peux pas vous en dire davantage là-dessus.

Ici, on arrive à gérer les erreurs que rencontre Ruby. Mais si on veut spécifier nous-même nos erreurs ? Comme celle de ne pas revenir demain ?