raise e o objeto exception
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
rescuesem classe, e a linha entre o que esserescuecaptura 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::ParameterMissingeActiveRecord::RecordInvalid, exceções de cursos anteriores, como alvos derescue SomeSpecificError => e.
Pontos-chave
raiseinterrompe 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
RuntimeErrorouZeroDivisionError, com.classe.messagepróprios. raise "text"monta umRuntimeError;raise SomeClass, "text"monta uma instância deSomeClasscom essa mensagem.- Este curso é sobre capturar essa subida de propósito em vez de deixá-la chegar ao topo e derrubar o programa.
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.