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:
-
FileNotFoundversusFileNotFoundError -
DatabaseExplodedversusDatabaseExplodedError
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