Sök…


Anmärkningar

Ett undantag är ett objekt som representerar förekomsten av ett exceptionellt tillstånd. Med andra ord indikerar det att något gick fel.

I Ruby kallas undantag ofta för fel . Det beror på att Exception finns som ett toppundantagsobjektelement, men användardefinierade exekveringsundantag är vanligtvis StandardError eller efterkommande.

Att göra ett undantag

För att höja ett undantag använder du Kernel#raise passerar undantagsklassen och / eller meddelandet:

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

Du kan också helt enkelt skicka ett felmeddelande. I det här fallet är meddelandet inslaget i en RuntimeError :

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

Här är ett exempel:

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"

Skapa en anpassad undantagstyp

Ett anpassat undantag är varje klass som utvidgar Exception eller en underklass för Exception .

I allmänhet bör du alltid utöka StandardError eller en efterkommer. Exception är vanligtvis för virtuella maskin- eller systemfel, räddning av dem kan förhindra att ett tvingat avbrott fungerar som förväntat.

# 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

Det är vanligt att ange undantag genom att lägga till Error i slutet:

  • ConnectionError
  • DontPanicError

Men när felet är självförklarande behöver du inte lägga till Error eftersom det skulle vara överflödigt:

  • FileNotFound vs FileNotFoundError
  • DatabaseExploded vs DatabaseExplodedError

Hantera ett undantag

Använd begin/rescue att fånga (rädda) ett undantag och hantera det:

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

En rescue är analog med ett catch på ett lockigt spetsspråk som C # eller Java.

En sådan rescue som denna räddar StandardError .

Obs: Var noga med att undvika att fånga Exception istället för standard StandardError . Exception inkluderar SystemExit och NoMemoryError och andra allvarliga undantag som du vanligtvis inte vill fånga. Överväg alltid att fånga StandardError (standard) istället.

Du kan också ange undantagsklassen som ska räddas:

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

Denna räddningsklausul kommer inte att fånga något undantag som inte är en CustomError .

Du kan också lagra undantaget i en specifik variabel:

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

Om du misslyckades med att hantera ett undantag kan du höja det när som helst i ett räddningsblock.

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

Om du vill försöka igen ditt begin , ring retry :

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

Du kan fastna i en slinga om du får ett undantag i varje försök. För att undvika detta, begränsa din retry_count till ett visst antal försök.

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

Du kan också tillhandahålla ett else block eller ett ensure . Ett else block kommer att köras när begin slutförs utan undantag kastas. Ett ensure kommer alltid att köras. Ett ensure är analogt med ett finally block på ett lockigt spetsspråk som C # eller 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

Om du är inne i en def , module eller class blocket, finns det ingen anledning att använda börja uttalande.

def foo
    ...
rescue
    ...
end

Hantera flera undantag

Du kan hantera flera fel i samma rescue :

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

Du kan också lägga till flera 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

rescue ordning är relevant: den första matchen är den som körs. Därför, om du sätter StandardError som det första villkoret och alla dina undantag ärver från StandardError , kommer de andra rescue aldrig att köras.

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

Vissa block har implicit undantagshantering som def , class och module . Dessa block låter dig hoppa över begin .

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

Lägga till information till (anpassade) undantag

Det kan vara bra att inkludera ytterligare information med ett undantag, t.ex. för loggningsändamål eller för att tillåta villkorad hantering när undantaget fångas:

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

Att höja undantaget:

raise CustomError.new(true)

Fånga undantaget och få tillgång till ytterligare information som tillhandahålls:

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow