Zoeken…


Opmerkingen

Een uitzondering is een object dat het optreden van een uitzonderlijke voorwaarde vertegenwoordigt. Met andere woorden, het geeft aan dat er iets mis is gegaan.

In Ruby worden uitzonderingen vaak fouten genoemd . Dat komt omdat de Exception bestaat als een uitzonderingsobjectelement op het hoogste niveau, maar door de gebruiker gedefinieerde uitvoeringsuitzonderingen zijn over het algemeen StandardError of afstammelingen.

Een uitzondering maken

Om een uitzondering op te heffen, gebruik je Kernel#raise door de uitzonderingsklasse en / of het bericht Kernel#raise passeren:

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

U kunt ook eenvoudig een foutmelding geven. In dit geval is het bericht verpakt in een RuntimeError :

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

Hier is een voorbeeld:

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"

Een aangepast uitzonderingstype maken

Een aangepaste uitzondering is elke klasse die de Exception of een subklasse van Exception uitbreidt.

Over het algemeen moet u StandardError of een afstammeling altijd uitbreiden. De Exception is meestal bedoeld voor fouten in de virtuele machine of het systeem. Als u ze oplost, kunt u voorkomen dat een gedwongen onderbreking naar verwachting werkt.

# 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

Het is gebruikelijk om uitzonderingen te benoemen door aan het einde het achtervoegsel Error voegen:

  • ConnectionError
  • DontPanicError

Wanneer de fout echter voor zichzelf spreekt, hoeft u het achtervoegsel Error niet toe te voegen, omdat dit overbodig zou zijn:

  • FileNotFound versus FileNotFoundError
  • DatabaseExploded versus DatabaseExplodedError

Behandeling van een uitzondering

Gebruik het begin/rescue om een uitzondering op te vangen (redding) en behandel deze:

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

Een rescue clausule is analoog aan een catch blok in een accolade taal zoals C # of Java.

Een blote rescue als deze redt StandardError .

Opmerking: zorg ervoor dat u geen Exception plaats van de standaard StandardError . De klasse Exception bevat SystemExit en NoMemoryError en andere ernstige uitzonderingen die u meestal niet wilt vangen. Overweeg altijd om StandardError (de standaard) te vangen.

U kunt ook de uitzonderingsklasse opgeven die moet worden gered:

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

Deze reddingsclausule zal geen uitzondering bevatten die geen CustomError .

U kunt de uitzondering ook opslaan in een specifieke variabele:

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

Als u een uitzondering niet kunt verwerken, kunt u deze op elk gewenst moment in een reddingsblok verhogen.

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

Als u het opnieuw proberen je begin te blokkeren, call retry :

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

Je kunt vastlopen in een lus als je een uitzondering krijgt bij elke nieuwe poging. Om dit te voorkomen, beperkt u uw retry_count tot een bepaald aantal pogingen.

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

U kunt ook een else blok of een blok ensure . Een else blok zal worden uitgevoerd wanneer het begin is voltooid zonder dat een uitzondering is opgetreden. Een ensure blokkering zal altijd worden uitgevoerd. Een blok ensure is analoog aan een blok finally in een krultaal zoals C # of 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

Als u zich in een def , module of class blok, is er geen noodzaak om te gebruiken het begin statement.

def foo
    ...
rescue
    ...
end

Meerdere uitzonderingen verwerken

U kunt meerdere fouten verwerken in dezelfde rescue :

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

U kunt ook meerdere rescue toevoegen:

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

De volgorde van de rescue is relevant: de eerste match is degene die wordt uitgevoerd. Als u StandardError als eerste voorwaarde stelt en al uw uitzonderingen erven van StandardError , worden de andere rescue nooit uitgevoerd.

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

Sommige blokken hebben impliciete uitzonderingsafhandeling zoals def , class en module . Deze blokken kunt u overslaan begin statement.

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

Informatie toevoegen aan (aangepaste) uitzonderingen

Het kan nuttig zijn om extra informatie op te nemen met een uitzondering, bijvoorbeeld voor logboekdoeleinden of om voorwaardelijke verwerking toe te staan wanneer de uitzondering wordt gevangen:

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

Opheffing van de uitzondering:

raise CustomError.new(true)

De uitzondering vangen en toegang krijgen tot de verstrekte aanvullende informatie:

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow