English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
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.
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.
#!/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>
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.
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
#!/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.
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.
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.
#!/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:
#!/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"]
À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.
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
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
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.
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
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.
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.
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
No exemplo a seguir, se o usuário digitar '!' em resposta a qualquer prompt, um throw termina a interação com o usuário.
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
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:
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:
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.