English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Exceções Ruby

As exceções e a execução sempre estão ligadas. Se você abrir um arquivo inexistente e não lidar com isso corretamente, seu programa é considerado de baixa qualidade.

Se ocorrer uma exceção, o programa para. As exceções são usadas para lidar com vários tipos de erros, que podem ocorrer durante a execução do programa, portanto, é necessário tomar ação apropriada para evitar que o programa pare completamente.

O Ruby oferece um mecanismo perfeito para o tratamento de exceções. Podemos begin/end no bloco, inclua o código que pode lançar exceções e use rescue a cláusula informa ao Ruby o tipo de exceção que deve ser tratada perfeitamente.

Sintaxe

begin #começo
 
 raise.. #lança exceção
 
rescue [ExceptionType = StandardException] #captura a exceção específica padrão é StandardException
 $! #indica a mensagem da exceção
 $@ #indica a posição do código onde ocorreu a exceção
else #outros exceções
 ..
ensure # independentemente de haver ou não exceção, entra no bloco de código
 
end # final

de begin até rescue Tudo no bloco rescue no bloco. end e

entre begin cada rescue cláusulas, Ruby compara a exceção lançada com cada parâmetro. Se a exceção nomeada na cláusula 'rescue' for do mesmo tipo da exceção lançada ou uma subclasse dessa exceção, a correspondência é bem-sucedida.

Se a exceção não corresponder a todos os tipos de erros especificados, podemos usar todos os rescue Cláusula após a qual usamos um senão cláusula.

Exemplo Online

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "Arquivo aberto com sucesso"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "\n"

O resultado de execução do exemplo acima é. Você pode ver que,STDIN substituiu file porqueao abrirfalhou.

#<IO:0xb7d16f84==#<IO:0xb7d16f84>

usar retry instrução

Você pode usar rescue O bloco captura a exceção e usa retry A sentença começa a ser executada no início do bloco begin bloco.

Sintaxe

begin
    # A exceção lançada por este código será capturada pela cláusula 'rescue' abaixo
rescue
    # Este bloco captura todos os tipos de exceções
    retry # Isso moverá o controle para o início de 'begin'
end

Exemplo Online

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "Arquivo aberto com sucesso"
   end
rescue
   fname = "existant_file"
   retry
end

Aqui está o fluxo de tratamento:

  • Ocorreu uma exceção ao abrir.

  • Pule para 'rescue'. 'fname' é reatribuído.

  • Pule para o início de 'begin' usando 'retry'.

  • A vez dessa vez, o arquivo foi aberto com sucesso.

  • Continue com o processo básico.

Atenção:Se o arquivo renomeado não existir, o código de exemplo tentará infinitamente. Portanto, use cautela no tratamento de exceções. retry.

usar raise instrução

Você pode usar raise A sentença lança uma exceção. O método abaixo lança uma exceção ao ser chamado. Sua segunda mensagem será exibida.

Sintaxe

raise 
 
ou
 
raise "Mensagem de erro" 
 
ou
 
raise ExceptionType, "Mensagem de erro"
 
ou
 
raise ExceptionType, "Mensagem de erro" condition

A primeira forma simplesmente reLANÇA a exceção atual (se não houver exceção atual, LANÇA um RuntimeError). Isso é usado em programas de exceção que precisam explicar a exceção antes de passar a exceção.

A segunda forma cria uma nova RuntimeError Exceção, define sua mensagem para a string fornecida. A exceção é lançada após a pilha de chamadas.

A terceira forma cria uma exceção usando o primeiro parâmetro e define a mensagem relacionada como o segundo parâmetro.

A quarta forma é semelhante à terceira, você pode adicionar qualquer condição adicional (como a menos que)para lançar uma exceção.

Exemplo Online

#!/usr/bin/ruby
 
begin  
    puts 'Estou antes do 'raise''.  
    raise 'Ocorreu um erro.'  
    puts 'Estou após o 'raise''.  
rescue  
    puts 'Estou sendo salvo'.  
end  
puts 'Estou após o bloco 'begin''.

O resultado de saída da execução do exemplo acima é:

Estou antes do 'raise'.  
Estou sendo salvo.  
Estou após o bloco 'begin'.

Outro exemplo raise Exemplo de uso:

Exemplo Online

#!/usr/bin/ruby
 
begin  
  raise 'Uma exceção de teste.'  
rescue Exception => e  
  puts e.message  
  puts e.backtrace.inspect  
end

O resultado de saída da execução do exemplo acima é:

Uma exceção de teste.
["main.rb:4"]

usar garantir instrução

Às vezes, você precisa garantir que alguns tratamentos sejam concluídos no final do bloco de código, independentemente de uma exceção ser lançada ou não. Por exemplo, você pode abrir um arquivo ao entrar no bloco e precisar garantir que o arquivo seja fechado quando sair do bloco.

garantir A cláusula faz isso. O 'ensure' é colocado após a última cláusula 'rescue' e contém um bloco de código que sempre será executado ao sair do bloco. Isso não importa se o bloco saiu normalmente, se lançou e tratou uma exceção ou se terminou devido a uma exceção não capturada,garantir O bloco sempre será executado.

Sintaxe

begin 
   #.. Processo
   #.. Lançar exceção
rescue 
   #.. Tratar erros 
garantir 
   #.. Certifique-se de que a execução seja concluída
   #.. Isso sempre será executado
end

Exemplo Online

begin
  raise 'Uma exceção de teste.'
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
garantir
  puts "Garantindo execução"
end

O resultado de saída da execução do exemplo acima é:

Uma exceção de teste.
["main.rb:4"]
Garantindo execução

usar senão instrução

se fornecido senão cláusula, geralmente colocada em rescue Depois da cláusula, qualquer garantir Antes.

senão A cláusula principal só é executada quando o corpo do código não lança uma exceção.

Sintaxe

begin 
   #.. Processo 
   #.. Lançar exceção
rescue 
   #.. Tratar erros
senão
   #.. Se não houver exceções, execute
garantir 
   #.. Certifique-se de que a execução seja concluída
   #.. Isso sempre será executado
end

Exemplo Online

begin
 # Lançar 'Uma exceção de teste.'
 puts "Eu não estou levantando uma exceção"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
senão
   puts "Parabéns"-- sem erros!"
garantir
  puts "Garantindo execução"
end

O resultado de saída da execução do exemplo acima é:

Eu não estou levantando uma exceção
Parabéns-- sem erros!
Garantindo execução

A variável $! pode ser usada para capturar a mensagem de erro lançada.

Catch e Throw

O mecanismo raise e rescue pode desistir da execução em caso de erro, às vezes é necessário sair de estruturas aninhadas profundas durante o processamento normal. Nesse caso, catch e throw entram em ação.

catch Define um bloco que usa um nome dado (pode ser um Symbol ou String) como etiqueta. O bloco será executado normalmente até encontrar um throw.

Sintaxe

throw :lablename
#.. Isso não será executado
catch :lablename do
#.. A match será executada após encontrar um throw
end
 
ou
 
throw :lablename condition
#.. Isso não será executado
catch :lablename do
#.. A match será executada após encontrar um throw
end

Exemplo Online

No exemplo a seguir, se o usuário digitar '!' em resposta a qualquer prompt, um throw termina a interação com o usuário.

Exemplo Online

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   throw :quitRequested if res == "!"
   return res
end
 
catch :quitRequested do
   nome = promptAndGet("Nome: ")
   idade = promptAndGet("Idade: ")
   sexo = promptAndGet("Sexo: ")
   # ..
   # Tratar informações
end
promptAndGet("Nome:")

O programa acima requer interação manual. Você pode tentar executá-lo no seu computador. O resultado da execução do exemplo acima é:

Nome: Ruby on Rails
Idade: 3
Sexo: !
Nome: Just Ruby

Classe Exception

As classes e módulos padrão do Ruby lançam exceções. Todas as classes de exceção formam uma hierarquia, incluindo a classe Exception no topo. A próxima camada é composta por sete tipos diferentes:

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal é outra exceção nessa camada, mas o interpretador Ruby usa apenas internamente.

A ScriptError e StandardError têm algumas subclasses, mas aqui não precisamos entender esses detalhes. A coisa mais importante é criar nossa própria classe de exceção, que deve ser subclass de Exception ou de sua subclass.

Vamos ver um exemplo:

Exemplo Online

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   end
end

Agora, veja o exemplo a seguir, que usará a exceção acima:

Exemplo Online

File.open(path, "w") do |file|
begin
    # Escrever dados ...
rescue
    # Ocorreu um erro
    raise FileSaveError.new($!)
end
end

Aqui, a linha mais importante é raise FileSaveError.new($!)Nós chamamos raise para indicar que uma exceção já ocorreu, passando-o para um novo exemplo de FileSaveError, devido a uma exceção específica que causou falha na gravação de dados.