Recherche…


Remarques

Une exception est un objet qui représente l'occurrence d'une condition exceptionnelle. En d'autres termes, cela indique que quelque chose s'est mal passé.

Dans Ruby, les exceptions sont souvent appelées erreurs . En effet, la classe Exception base existe en tant qu'élément d'objet d'exception de niveau supérieur, mais les exceptions d'exécution définies par l'utilisateur sont généralement StandardError ou des descendants.

Lever une exception

Pour générer une exception, utilisez le Kernel#raise passant la classe et / ou le message d'exception:

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

Vous pouvez également simplement transmettre un message d'erreur. Dans ce cas, le message est enveloppé dans une RuntimeError :

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

Voici un exemple:

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"

Création d'un type d'exception personnalisé

Une exception personnalisée est toute classe qui étend Exception ou une sous-classe d' Exception .

En général, vous devez toujours étendre StandardError ou un descendant. La famille des Exception concerne généralement les erreurs de machine virtuelle ou de système, les récupérer peut empêcher une interruption forcée de fonctionner comme prévu.

# 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

Il est courant de nommer des exceptions en ajoutant le suffixe d' Error à la fin:

  • ConnectionError
  • DontPanicError

Toutefois, lorsque l'erreur est explicite, vous n'avez pas besoin d'ajouter le suffixe d' Error car il serait redondant:

  • FileNotFound vs FileNotFoundError
  • DatabaseExploded vs DatabaseExplodedError

Gérer une exception

Utilisez le bloc begin/rescue pour intercepter (sauver) une exception et la gérer:

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

Une clause de rescue est analogue à un bloc catch dans une accolade comme C # ou Java.

Un rescue brutal comme celui-ci sauve StandardError .

Remarque: veillez à ne pas intercepter Exception place de StandardError par défaut. La classe Exception inclut SystemExit et NoMemoryError et d'autres exceptions graves que vous ne souhaitez généralement pas intercepter. Toujours envisager d'attraper StandardError (valeur par défaut) à la place.

Vous pouvez également spécifier la classe d'exception à récupérer:

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

Cette clause de secours n'acceptera aucune exception qui n'est pas une CustomError .

Vous pouvez également stocker l'exception dans une variable spécifique:

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 vous ne parvenez pas à gérer une exception, vous pouvez l'augmenter à tout moment dans un bloc de secours.

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

Si vous voulez retenter votre begin bloc, appelez retry :

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

Vous pouvez être bloqué dans une boucle si vous attrapez une exception dans chaque tentative. Pour éviter cela, limitez votre retry_count de retry_count à un certain nombre d'essais.

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

Vous pouvez également fournir un else bloc ou un bloc d’ ensure . Un bloc else sera exécuté lorsque le bloc de begin termine sans qu'une exception soit lancée. Un bloc d’ ensure sera toujours exécuté. Un bloc d' ensure est analogue à un bloc finally dans une accolade comme C # ou 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 vous vous trouvez dans un bloc def , module ou class , il n'est pas nécessaire d'utiliser l'instruction begin.

def foo
    ...
rescue
    ...
end

Gestion de plusieurs exceptions

Vous pouvez gérer plusieurs erreurs dans la même déclaration de rescue :

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

Vous pouvez également ajouter plusieurs déclarations 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

L'ordre des blocs de rescue est pertinent: le premier match est celui exécuté. Par conséquent, si vous placez StandardError comme première condition et que toutes vos exceptions héritent de StandardError , les autres instructions de rescue ne seront jamais exécutées.

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

Certains blocs ont une gestion implicite des exceptions comme def , class et module . Ces blocs vous permettent d'ignorer l'instruction begin .

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

Ajout d'informations à des exceptions (personnalisées)

Il peut être utile d'inclure des informations supplémentaires avec une exception, par exemple à des fins de journalisation ou pour permettre une gestion conditionnelle lorsque l'exception est interceptée:

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

En soulevant l'exception:

raise CustomError.new(true)

Récupérer l'exception et accéder aux informations supplémentaires fournies:

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


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow