raise e o objeto exception

Prévia grátis 3 min de leitura

Um crash que você já viu

Num curso anterior, um código seu levantou ActiveRecord::RecordNotFound ou ActiveModel::ForbiddenAttributesError. A página quebrou, apareceu um stack trace, e a correção foi mudar o código para o erro parar de acontecer. Este curso trata do que acontece nesse momento, e de como assumir o controle dele em vez de só evitá-lo.

def open_account(balance)
  raise "balance cannot be negative" if balance < 0
  balance
end

open_account(-50)

Rodar isso derruba o programa:

RuntimeError: balance cannot be negative

raise é uma palavra-chave do Ruby; o Rails não a inventou. Chamado com uma string, ele monta um RuntimeError com essa string como mensagem e interrompe a execução normal na hora. A exceção sobe por todas as chamadas de método até algo capturá-la ou o programa morrer.

Uma exceção é um objeto

RuntimeError, ArgumentError, ZeroDivisionError e ActiveRecord::RecordNotFound são todos classes, e toda exceção levantada é uma instância de uma delas, como qualquer outro objeto Ruby.

begin
  1 / 0
rescue => e
  e.class
  # => ZeroDivisionError
  e.message
  # => "divided by 0"
end

e.class e e.message funcionam porque e é um objeto na memória com estado próprio, e não um sinal de crash sem forma. Toda classe de exceção do Ruby acaba herdando de Exception, a raiz da hierarquia. O raise também aceita uma classe e uma mensagem:

raise ArgumentError, "amount must be a number"

Isso monta um ArgumentError com essa mensagem e o levanta. É o mesmo mecanismo de antes, dando nome à classe em vez de cair no RuntimeError padrão.

Por que isso vale um curso inteiro

Uma exceção não tratada faz mais que imprimir uma mensagem feia. Ela para o método em que aconteceu, depois o método que o chamou, depois o seguinte, até algum código no caminho dizer "deixa comigo" ou o programa parar. Um RecordNotFound que ninguém captura sobe até a requisição do Rails. Aí o framework precisa entrar e transformá-lo num 500 ou, com o tratamento certo, numa página amigável de "não encontrado". O resto deste curso é sobre escrever esse "deixa comigo" de propósito. Ele cobre begin/rescue/else/ensure, a diferença entre capturar um problema específico e capturar quase tudo, e classes de exceção suas, com mensagens que explicam o que deu errado.

O que este curso cobre

  • begin/rescue/else/ensure/end, a estrutura completa para capturar uma exceção levantada e reagir a ela.
  • Resgatar uma classe de exceção específica contra um rescue sem classe, e a linha entre o que esse rescue captura e o que ele deixa passar de propósito.
  • ensure, e a prova de que ele roda aconteça o que acontecer no bloco acima.
  • Escrever uma classe de exceção própria e levantá-la com uma mensagem que diz algo.
  • ActiveRecord::RecordNotFound, ActiveModel::ForbiddenAttributesError, ActionController::ParameterMissing e ActiveRecord::RecordInvalid, exceções de cursos anteriores, como alvos de rescue SomeSpecificError => e.

Pontos-chave

  • raise interrompe a execução normal e sobe por todos os métodos chamadores até algo capturar a exceção ou o programa parar.
  • Uma exceção é um objeto, instância de uma classe como RuntimeError ou ZeroDivisionError, com .class e .message próprios.
  • raise "text" monta um RuntimeError; raise SomeClass, "text" monta uma instância de SomeClass com essa mensagem.
  • Este curso é sobre capturar essa subida de propósito em vez de deixá-la chegar ao topo e derrubar o programa.
Aula 1 de 7 · grátis

Continue com a aula 2

begin/rescue: capturando uma exception específica

begin e rescue para capturar uma classe específica, a ordem de várias cláusulas e o rescue no método inteiro.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...