Ruby Language
Uitzonderingen
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
versusFileNotFoundError
-
DatabaseExploded
versusDatabaseExplodedError
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