Le eccezioni sono una parte fondamentale della programmazione in Ruby, in quanto consentono agli sviluppatori di gestire gli errori con grazia e di garantire applicazioni robuste e tolleranti agli errori. Il meccanismo di gestione delle eccezioni di Ruby è intuitivo ma potente e consente agli sviluppatori di sollevare errori quando qualcosa va storto e di salvarli per evitare crash dell'applicazione. In questa guida di 2000 parole, esploreremo come sollevare e salvare le eccezioni in Ruby, coprendo le basi, le tecniche avanzate, le migliori pratiche e gli esempi reali.
Cosa sono le eccezioni in Ruby?
Le eccezioni in Ruby sono oggetti che rappresentano errori o condizioni inattese durante l'esecuzione del programma. Quando si verifica un errore, come il tentativo di dividere per zero, l'accesso a un file inesistente o un errore di rete, Ruby solleva un'eccezione. Se non viene gestita, l'eccezione fa terminare il programma con un messaggio di errore.
Il sistema di eccezioni di Ruby è costruito attorno all'elemento Eccezione che funge da radice della gerarchia delle eccezioni. Sottoclassi come StandardError, RuntimeError, ArgumentError, E NoMethodError gestire tipi specifici di errori. Gli sviluppatori possono anche definire classi di eccezioni personalizzate per rappresentare errori specifici dell'applicazione.
La gestione delle eccezioni in Ruby ruota attorno a due azioni chiave:
- Innalzamento: Attivazione di un'eccezione quando si verifica un errore.
- Salvataggio: Catturare e gestire le eccezioni per evitare gli arresti anomali del programma.
Vediamo come sollevare e salvare le eccezioni in modo efficace.
Sollevare eccezioni in Ruby
Sollevare un'eccezione è il processo di segnalazione di un errore o di una condizione inaspettata. Ruby fornisce l'opzione aumento (e il suo alias fallire) per attivare le eccezioni.
Il aumento Metodo
Il modo più semplice per sollevare un'eccezione è usare l'opzione aumento senza argomenti, che solleva un problema di Errore di runtime (una sottoclasse di Errore standard):
rubino sollevare # => RuntimeError: eccezione non gestita
Si può anche fornire un messaggio di errore:
rubino raise "Qualcosa è andato storto!" # => RuntimeError: Qualcosa è andato storto!
Per sollevare una classe di eccezione specifica, passare la classe come primo parametro e il messaggio come secondo:
rubino sollevare ArgumentError, "Input non valido fornito". # => ArgumentError: Input non valido fornito
Classi di eccezioni personalizzate
Per applicazioni più complesse, è possibile definire classi di eccezioni personalizzate per rappresentare errori specifici. Le eccezioni personalizzate ereditano da Errore standard o una delle sue sottoclassi, per garantire la compatibilità con il comportamento di salvataggio predefinito di Ruby.
Esempio:
rubino classe AuthenticationError AuthenticationError: Credenziali non valide
Definendo Errore di autenticazioneè possibile gestire gli errori legati all'autenticazione separatamente dagli errori generici.
Sollevare eccezioni con causa
Ruby consente di allegare una "causa" a un'eccezione, utile per il debug. La causa è l'eccezione originale che ha portato a quella attuale. Utilizzate l'opzione eccezione per accedervi:
rubino iniziare raise "Errore originale" rescue => e raise "Nuovo errore" # L'errore originale è conservato come causa fine
È possibile verificare la causa con e.causa:
rubino
iniziare
iniziare
raise "Errore originale"
rescue => e
sollevare "Nuovo errore"
fine
salvataggio => e
mette e.message # => Nuovo errore
puts e.cause.message # => Errore originale
fineSalvataggio delle eccezioni
Il salvataggio delle eccezioni consente di catturare e gestire gli errori con grazia, evitando che il programma si blocchi. Ruby utilizza il metodo inizio/soccorso per gestire le eccezioni.
Il inizio/soccorso Blocco
La struttura di base di un inizio/soccorso Il blocco è:
rubino iniziare # Codice che potrebbe sollevare un'eccezione salvataggio # Gestire l'eccezione fine
Esempio:
rubino iniziare risultato = 10 / 0 salvataggio mette "Si è verificato un errore!" fine Uscita #: Si è verificato un errore!
Per impostazione predefinita, soccorso catture Errore standard e le sue sottoclassi. Se non si specifica una classe di eccezione, è equivalente a salvataggio StandardError.
Gestione di eccezioni specifiche
Per gestire eccezioni specifiche, specificare la classe di eccezione nel parametro soccorso clausola:
rubino iniziare risultato = 10 / 0 salvataggio ZeroDivisionError puts "Impossibile dividere per zero!" salvataggio ArgumentError mette "Argomento non valido fornito!" fine # Uscita: Impossibile dividere per zero!
È anche possibile catturare l'oggetto dell'eccezione per un'ulteriore verifica:
rubino
iniziare
raise ArgumentError, "Input non valido"
salvataggio ArgumentError => e
mette "Errore: #{e.message}".
fine
Uscita #: Errore: Ingresso non validoUtilizzando altro E garantire
Ruby fornisce due clausole aggiuntive per la gestione delle eccezioni:
altro: Esegue se non viene sollevata alcuna eccezione.garantire: Esegue indipendentemente dal verificarsi di un'eccezione, utile per le operazioni di pulizia.
Esempio:
rubino
inizia
mette "Esecuzione dell'operazione..."
risultato = 10 / 2
salvataggio ZeroDivisionError
puts "Impossibile dividere per zero!"
else
puts "Operazione riuscita: #{risultato}"
assicura
mette "Pulizia..."
fine
# Uscita:
# Esecuzione dell'operazione...
# Operazione riuscita: 5
# Pulizia...Se si verifica un'eccezione:
rubino
inizia
mette "Esecuzione dell'operazione..."
risultato = 10 / 0
salvataggio ZeroDivisionError
puts "Impossibile dividere per zero!"
else
puts "Operazione riuscita: #{risultato}"
assicura
mette "Pulizia..."
fine
# Uscita:
# Esecuzione dell'operazione...
# Impossibile dividere per zero!
# Pulizia...Il riprovare Parola chiave
Il riprovare consente di riprovare l'operazione inizio dopo che è stata catturata un'eccezione. Questo è utile per scenari come la ripetizione di richieste di rete fallite.
Esempio:
rubino
tentativi = 0
iniziare
tentativi += 1
puts "Tentativo #{tentativi}"
raise "Connessione fallita"
salvataggio
riprova se tentativi < 3
mette "Rinuncia dopo #{tentativi} tentativi".
fine
Uscita #:
# Tentativo 1
# Tentativo 2
# Tentativo 3
# Rinuncia dopo 3 tentativiUsare con cautela i tentativi per evitare loop infiniti.
Migliori pratiche per la gestione delle eccezioni
- Eccezioni specifiche per il soccorso: Evitare la nudità
soccorsoperché catturano tutte le clausoleErrore standarde può nascondere errori imprevisti. Specificate le eccezioni esatte che vi aspettate.rubino # Cattivo iniziare Codice # salvataggio # Cattura tutto fine # Buono iniziare # Codice salvare ArgumentError, TypeError # Gestire errori specifici fine
- Mantenere i blocchi di salvataggio piccoli: Avvolgere solo il codice che potrebbe sollevare un'eccezione. Questo migliora la leggibilità ed evita di catturare errori non correlati.
- Fornire messaggi di errore significativi: Quando si sollevano delle eccezioni, includere messaggi chiari e perseguibili per facilitare il debugging.
- Utilizzare le eccezioni personalizzate per la logica di dominio: Creare classi di eccezioni personalizzate per errori specifici dell'applicazione, per rendere il codice più espressivo e manutenibile.
- Evitare l'uso eccessivo di eccezioni per il controllo del flusso: Le eccezioni servono per casi eccezionali, non per controllare il flusso del programma. Usare i condizionali per gli scenari previsti.
rubino # Cattivo iniziare valore = hash[:key] salvataggio valore = nil fine # Buono valore = hash[:key] || nil
- Risorse per la pulizia con
garantire: Utilizzogarantireper chiudere file, connessioni al database o altre risorse, anche se si verifica un'eccezione.
Esempi del mondo reale
Gestione dei file
La lettura di un file può sollevare eccezioni come Errno::ENOENT (file non trovato) o Errno::EACCES (permesso negato). Ecco come gestirli:
rubino
iniziare
File.open("inesistente.txt", "r") do |file|
mette file.read
fine
salvare Errno::ENOENT
puts "File non trovato!"
rescue Errno::EACCES
mette "Autorizzazione negata!"
assicura
mette "Operazione file completata".
fine
# Output: File non trovato!
# Operazione file completata.Chiamate API
Quando si effettuano richieste HTTP, è possibile che si verifichino errori di rete o risposte non valide. Utilizzando l'opzione httparty gemma:
rubino
richiedere 'httparty'
iniziare
risposta = HTTParty.get('https://api.example.com/data')
rescue HTTParty::Error => e
mette "Richiesta API fallita: #{e.message}".
salvataggio SocketError
puts "Errore di rete: Impossibile connettersi al server"
else
mette "Risposta ricevuta: #{risposta.body}".
fineGestione personalizzata delle eccezioni in una classe
Ecco un esempio di classe che elabora pagamenti e utilizza eccezioni personalizzate:
rubino
classe PaymentError < StandardError; fine
classe InsufficientFundsError < PaymentError; fine
classe InvalidCardError card.balance
card.balance -= importo
puts "Il pagamento di #{importo} è stato elaborato con successo".
fine
privato
def valid_card?(card)
card.number.length == 16
fine
fine
classe Carta
attr_accessor :number, :balance
def initialize(numero, saldo)
@numero = numero
@bilancio = bilancio
fine
fine
carta = Card.new("1234567890123456", 50)
processore = PaymentProcessor.new
iniziare
processor.process_payment(100, carta)
salvataggio InsufficientFundsError => e
mette "Errore: #{e.message}".
rescue InvalidCardError => e
puts "Errore: #{e.message}"
fine
Uscita #: Errore: Fondi insufficientiGestione avanzata delle eccezioni
Soccorsi annidati
È possibile annidare inizio/soccorso per gestire le eccezioni a diversi livelli:
rubino
iniziare
iniziare
sollevare "Errore interno"
salvataggio
mette "Errore interno rilevato"
sollevare "Errore esterno"
fine
salvataggio
mette "Errore esterno rilevato"
fine
# Uscita:
# Errore interno rilevato
# Errore esterno rilevatoGerarchia delle eccezioni
La comprensione della gerarchia delle eccezioni di Ruby è fondamentale. Le classi chiave includono:
EccezioneM: Classe radice per tutte le eccezioni.Errore standard: Predefinito persoccorsosenza una classe; la maggior parte delle eccezioni incorporate ereditano da essa.Errore di runtime: Predefinito peraumentosenza classe.NoMethodError, ArgumentError, TypeErrorecc.: tipi di errore specifici.
Per catturare tutte le eccezioni (comprese quelle nonErrore standard come Uscita dal sistema), utilizzare salvataggio Eccezione:
rubino iniziare uscire salvataggio dell'eccezione mette "Uscita catturata" fine Uscita #: Uscita catturata
Utilizzando salvataggio_da in Rails
In Ruby on Rails, si può usare salvataggio_da nei controllori per gestire le eccezioni a livello globale:
rubino
classe ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :not_found
privato
def not_found
renderà il file: 'public/404.html', status: :not_found
fine
fineQuesto approccio centralizza la gestione delle eccezioni per controllori specifici.
Le insidie più comuni da evitare
- Catturare tutte le eccezioni alla cieca: Utilizzo
soccorsosenza specificare una classe di eccezione può nascondere dei bug. - Uso eccessivo
riprovare: Riprovare all'infinito può portare a loop infiniti o a mascherare problemi di fondo. - Ignorare i dettagli delle eccezioni: Ispezionare sempre l'oggetto eccezione (
e.message, e.backtrace) per il debug. - Sollevamento di errori non standard: Evitare di sollevare eccezioni che non ereditano da
Errore standardpoiché non saranno catturati per impostazione predefinita.soccorsoclausole. - Non pulire le risorse: Dimenticare di usare
garantirepossono lasciare file o connessioni aperte.
Conclusione
Sollevare e salvare eccezioni in Ruby è un modo potente per gestire gli errori e costruire applicazioni robuste. A RailsCarma, un'azienda leader Società di sviluppo Ruby on Railse sfruttiamo queste tecniche per creare soluzioni affidabili e manutenibili. Utilizzando aumento per segnalare gli errori, soccorso per catturarli e strumenti come riprovare, altrimenti, E garantireGli sviluppatori possono gestire gli errori in modo efficace. Le classi di eccezioni personalizzate e le clausole di salvataggio specifiche aggiungono chiarezza e precisione al codice. Seguire le migliori pratiche, come il salvataggio di eccezioni specifiche, la riduzione delle dimensioni dei blocchi di salvataggio e l'uso di messaggi di errore significativi, garantisce un codice manutenibile e affidabile.
Che si tratti di operazioni su file, chiamate API o logica specifica del dominio, il sistema di gestione delle eccezioni di Ruby offre la flessibilità necessaria per affrontare gli errori con grazia. Padroneggiando queste tecniche ed evitando le insidie più comuni, RailsCarma aiuta le aziende a costruire applicazioni Ruby resilienti che gestiscono gli errori con sicurezza.