Hävning och räddning av undantag i Ruby

Så här samlar du in och räddar undantag i Ruby

Undantag är en grundläggande del av programmering i Ruby, vilket gör det möjligt för utvecklare att hantera fel på ett elegant sätt och säkerställa robusta, feltoleranta applikationer. Rubys undantagshanteringsmekanism är intuitiv men ändå kraftfull, vilket gör det möjligt för utvecklare att skapa fel när något går fel och rädda dem för att förhindra programkrascher. I den här guiden på 2000 ord utforskar vi hur man skapar och räddar undantag i Ruby, och täcker grunderna, avancerade tekniker, bästa praxis och verkliga exempel.

Vad är undantag i Ruby?

Undantag i Ruby är objekt som representerar fel eller oväntade förhållanden under programkörning. När ett fel uppstår - till exempel ett försök att dividera med noll, åtkomst till en icke-existerande fil eller ett nätverksfel - skapar Ruby ett undantag. Om det inte hanteras leder undantaget till att programmet avslutas med ett felmeddelande.

Rubys undantagssystem är uppbyggt kring Undantag klassen, som fungerar som roten i undantagshierarkin. Underklasser som Standardfel, Runtidsfel, Argumentfel, och IngenMetodFel hantera specifika typer av fel. Utvecklare kan också definiera egna undantagsklasser för att representera applikationsspecifika fel.

Undantagshantering i Ruby kretsar kring två nyckelåtgärder:

  • Höjning: Utlösning av ett undantag när ett fel inträffar.
  • Räddning: Fånga upp och hantera undantag för att förhindra programkrascher.

Nu ska vi titta närmare på hur man effektivt höjer och räddar undantag.

Undantag i Ruby

Ett undantag är en process som signalerar att ett fel eller ett oväntat tillstånd har inträffat. Ruby tillhandahåller höja metod (och dess alias misslyckas) för att utlösa undantag.

Den höja Metod

Det enklaste sättet att skapa ett undantag är att använda höja metod utan argument, vilket ger upphov till en RuntimeFel (en underklass till Standardfel):

rubin
höja
# => RuntimeError: ohanterat undantag

Du kan också ange ett felmeddelande:

ruby
raise "Något gick fel!"
# => RuntimeError: Något gick fel!

Om du vill ta upp en specifik undantagsklass skickar du klassen som första argument och meddelandet som andra:

ruby
raise ArgumentError, "Invalid input provided"
# => ArgumentError: Ogiltig inmatning tillhandahållen

Anpassade undantagsklasser

För mer komplexa applikationer kanske du vill definiera egna undantagsklasser för att representera specifika fel. Anpassade undantag ärver från Standardfel eller en av dess underklasser för att säkerställa kompatibilitet med Rubys standardräddningsbeteende.

Exempel:

ruby
class AuthenticationError  AuthenticationError: Ogiltiga autentiseringsuppgifter

Genom att definiera Autentiseringsfelkan du hantera autentiseringsrelaterade fel separat från generiska fel.

Undantag med motivering

Med Ruby kan du koppla en "orsak" till ett undantag, vilket är användbart för felsökning. Orsaken är det ursprungliga undantaget som ledde till det aktuella undantaget. Använd undantag metod för att komma åt den:

ruby
börja
  raise "Ursprungligt fel"
räddning => e
  raise "Nytt fel" # Det ursprungliga felet bevaras som orsak
avsluta

Du kan inspektera orsaken med e.orsak:

ruby
börja
  börja
    raise "Ursprungligt fel"
  räddning => e
    höja "Nytt fel"
  slut
räddning => e
  puts e.message # => Nytt fel
  puts e.cause.message # => Ursprungligt fel
slut

Räddning av undantag

Genom att rädda undantag kan du fånga upp och hantera fel på ett elegant sätt och förhindra att ditt program kraschar. Ruby använder påbörja/räddning block för att hantera undantag.

Den Börja/räddning Block

Den grundläggande strukturen i en påbörja/räddning block är:

ruby
börja
  # Kod som kan ge upphov till ett undantag
Rädda
  # Hantera undantaget
avsluta

Exempel:

ruby
börja
  resultat = 10 / 0
räddning
  puts "Ett fel inträffade!"
slut
# Utgång: Ett fel inträffade!

Som standard, räddning fångar Standardfel och dess underklasser. Om du inte anger någon undantagsklass är det likvärdigt med räddning StandardError.

Hantering av specifika undantag

Om du vill hantera specifika undantag anger du undantagsklassen i räddning klausul:

ruby
börja
  resultat = 10 / 0
räddar ZeroDivisionError
  puts "Kan inte dividera med noll!"
räddning ArgumentFel
  puts "Ogiltigt argument angavs!"
slut
# Utmatning: Kan inte dividera med noll!

Du kan också fånga upp undantagsobjektet för vidare granskning:

ruby
börja
  raise ArgumentError, "Ogiltig inmatning"
rescue ArgumentError => e
  puts "Fel: #{e.message}"
slut
# Utmatning: Fel: Ogiltig inmatning

Använder sig av annan och säkerställa

Ruby innehåller två ytterligare klausuler för undantagshantering:

  • annan: Utförs om inget undantag har uppstått.
  • säkerställa: Exekveras oavsett om ett undantag inträffar, användbart för rensningsuppgifter.

Exempel:

ruby
börja
  puts "Utför operation ..."
  resultat = 10 / 2
räddar ZeroDivisionError
  puts "Kan inte dividera med noll!"
else
  puts "Operationen lyckades: #{resultat}"
säkerställa
  puts "Städa upp ..."
slut
# Utgång:
# Utför operation...
# Operationen lyckades: 5
# Städa upp...

Om ett undantag inträffar:

ruby
börja
  puts "Utför operation ..."
  resultat = 10 / 0
räddar ZeroDivisionError
  puts "Kan inte dividera med noll!"
else
  puts "Operationen lyckades: #{resultat}"
säkerställa
  puts "Städa upp ..."
slut
# Utgång:
# Utför operation...
# Kan inte dividera med noll!
# Städar upp...

Den Försök igen Sökord

Den Försök igen nyckelordet kan du försöka igen med Börja blockera efter att ett undantag har fångats. Detta är användbart för scenarier som att försöka på nytt med misslyckade nätverksförfrågningar.

Exempel:

ruby
försök = 0
börja
  försök += 1
  puts "Försök #{försök}"
  raise "Anslutningen misslyckades"
räddning
  Försök igen om försök < 3
  puts "Ger upp efter #{försök} försök"
slut
# Utmatning:
# Försök 1
# Försök 2
# Försök 3
# Ger upp efter 3 försök

Använd retry försiktigt för att undvika oändliga loopar.

Bästa praxis för undantagshantering

  1. Särskilda undantag för räddningstjänst: Undvik nakna räddning klausuler, eftersom de fångar alla Standardfel underklasser och kan dölja oväntade fel. Specificera exakt vilka undantag du förväntar dig.
    rubin
    # Bad
    börja
      # Kod
    räddning
      # Fångar upp allt
    slut
    
    # Bra
    börja
      # Kod
    rescue ArgumentFel, TypFel
      # Hantera specifika fel
    avsluta
  2. Håll räddningsblocken små: Packa bara in den kod som kan ge upphov till ett undantag. Detta förbättrar läsbarheten och förhindrar att orelaterade fel fångas upp.
  3. Tillhandahålla meningsfulla felmeddelanden: När du gör undantag, inkludera tydliga, handlingsbara meddelanden för att underlätta felsökning.
  4. Använda anpassade undantag för domänlogik: Skapa egna undantagsklasser för applikationsspecifika fel för att göra din kod mer uttrycksfull och underhållbar.
  5. Undvik att överanvända undantag för flödeskontroll: Undantag är till för exceptionella fall, inte för att styra programflödet. Använd conditionals för förväntade scenarier.
    rubin
    # Bad
    börja
    värde = hash[:nyckel]
    räddning
    värde = nil
    slut
    
    # Bra
    värde = hash[:nyckel] || nil
  6. Städa upp resurser med säkerställa: Användning säkerställa för att stänga filer, databasanslutningar eller andra resurser, även om ett undantag inträffar.

Exempel från den verkliga världen

Filhantering

Läsning av en fil kan ge upphov till undantag som Errno::ENOENT (filen hittades inte) eller Errno::EACCES (tillstånd nekat). Så här hanterar du dem:

ruby
börja
  File.open("nonexistent.txt", "r") do |file|
    sätter fil.läs
  slut
räddning Errno::ENOENT
  puts "Filen hittades inte!"
räddning Errno::EACCES
  puts "Tillstånd nekat!"
säkerställa
  puts "Filoperationen slutförd."
slut
# Utmatning: Filen hittades inte!
# Filoperationen slutförd.

API-anrop

När du gör HTTP-förfrågningar kan det hända att du stöter på nätverksfel eller ogiltiga svar. Med hjälp av httparty gem:

ruby
kräver 'httparty'

börja
  svar = HTTParty.get('https://api.example.com/data')
räddning HTTParty::Fel => e
  puts "API-begäran misslyckades: #{e.message}"
räddning SocketError
  puts "Nätverksfel: Kunde inte ansluta till servern"
annat
  puts "Mottaget svar: #{response.body}"
slut

Anpassad undantagshantering i en klass

Här är ett exempel på en klass som hanterar betalningar och använder anpassade undantag:

ruby
class PaymentError < Standardfel; end
class InsufficientFundsError < Betalningsfel; end
class InvalidCardError  card.balance
    card.balance -= belopp
    puts "Betalning på #{belopp} behandlad framgångsrikt"
  slut

  privat
  def giltigt_kort?(kort)
    kort.nummer.längd == 16
  slut
slut

klass Kort
  attr_accessor :nummer, :balans
  def initialize(nummer, saldo)
    @number = antal
    @balans = balans
  slut
slut

kort = Card.new("1234567890123456", 50)
processor = PaymentProcessor.new

börja
  processor.process_payment(100, kort)
rescue InsufficientFundsError => e
  puts "Fel: #{e.message}"
rescue InvalidCardError => e
  puts "Fel: #{e.message}"
slut
# Utmatning: Fel: Inte tillräckligt med medel

Avancerad undantagshantering

Nested Rescues

Du kan bygga bo påbörja/räddning block för att hantera undantag på olika nivåer:

ruby
börja
  börja
    raise "Inre fel"
  räddning
    puts "Fångade upp inre fel"
    höja "Yttre fel"
  slut
Räddning
  puts "Fångade yttre fel"
slut
# Utmatning:
# Fångade inre fel
# Fångade yttre fel

Undantagshierarki

Att förstå Rubys undantagshierarki är avgörande. Viktiga klasser inkluderar:

  • UndantagM: Rotklass för alla undantag.
  • Standardfel: Standard för räddning utan klass; de flesta inbyggda undantag ärver från den.
  • RuntimeFel: Standard för höja utan en klass.
  • NoMethodError, ArgumentError, TypeErroretc.: Specifika feltyper.

För att fånga upp alla undantag (inklusive ickeStandardfel sådana som Systemavslut), använd rescue Exception:

ruby
börja
  avsluta
räddning Exception
  puts "Fångad utgång"
slut
# Utgång: Fångad utgång

Använder sig av räddning_från i Rails

I Ruby on Rails kan du använda räddning_från i styrenheter för att hantera undantag globalt:

ruby
klass ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, med: :not_found

  privat

  def not_found
    renderar fil: 'public/404.html', status: :not_found
  slut
slut

Detta tillvägagångssätt centraliserar undantagshanteringen för specifika styrenheter.

Vanliga fallgropar att undvika

  1. Fånga alla undantag blint: Använda räddning utan att ange en undantagsklass kan dölja buggar.
  2. Överanvändning Försök igen: Att försöka igen på obestämd tid kan leda till oändliga loopar eller dölja underliggande problem.
  3. Ignorera detaljer om undantag: Inspektera alltid undantagsobjektet (e.meddelande, e.bakspårning) för felsökning.
  4. Uppmärksamma fel som inte är standardfel: Undvik att skapa undantag som inte ärver från Standardfel, eftersom de inte kommer att fångas upp som standard räddning klausuler.
  5. Städa inte upp resurser: Glömmer att använda säkerställa kan lämna filer eller anslutningar öppna.

Slutsats

Att lyfta fram och rädda undantag i Ruby är ett kraftfullt sätt att hantera fel och bygga robusta applikationer. På RailsCarmaett ledande Ruby on Rails utvecklingsföretaganvänder vi dessa tekniker för att skapa tillförlitliga och underhållbara lösningar. Genom att använda höja för att signalera fel, räddning för att fånga dem, och verktyg som försök igen, annars, och säkerställakan utvecklare hantera fel på ett effektivt sätt. Anpassade undantagsklasser och specifika räddningsklausuler gör din kod tydligare och mer precis. Genom att följa bästa praxis, till exempel att rädda specifika undantag, hålla räddningsblocken små och använda meningsfulla felmeddelanden, får du underhållbar och tillförlitlig kod.

Oavsett om du hanterar filoperationer, API-anrop eller domänspecifik logik, ger Rubys undantagshanteringssystem flexibiliteten att hantera fel på ett elegant sätt. Genom att behärska dessa tekniker och undvika vanliga fallgropar hjälper RailsCarma företag att bygga motståndskraftiga Ruby-applikationer som hanterar fel med förtroende.

relaterade inlägg

Om inläggsförfattare

Lämna en kommentar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *


sv_SESwedish