Como eu levanto uma exceção no Rails para que ela se comporte como outras exceções do Rails?

91

Eu gostaria de levantar uma exceção para que ele faça a mesma coisa que uma exceção normal do Rails faz. Em especial, mostre a exceção e o rastreamento de pilha no modo de desenvolvimento e mostre a página "Desculpe, mas algo deu errado" no modo de produção.

Tentei o seguinte:

raise "safety_care group missing!" if group.nil?

Mas ele simplesmente grava "ERROR signing up, group missing!"no arquivo development.log

Chirag Patel
fonte
2
a mensagem de erro que você postou não parece vir dessa exceção (é uma mensagem diferente) é realmente isso que você está vendo?
levinalex

Respostas:

139

Você não precisa fazer nada de especial, deve apenas funcionar.

Quando eu tiver um aplicativo Rails novo com este controlador:

class FooController < ApplicationController
  def index
    raise "error"
  end
end

e vai para http://127.0.0.1:3000/foo/

Estou vendo a exceção com um rastreamento de pilha.

Você pode não ver todo o stacktrace no log do console porque o Rails (desde 2.3) filtra as linhas do stack trace que vêm do próprio framework.

Veja config/initializers/backtrace_silencers.rbno seu projeto Rails

levinalex
fonte
2
Excelente resposta concisa.
rcd
1
O link skitch (vendo a exceção com um rastreamento de pilha) não está mais funcionando
Asaf de
@levinalex isso será seguro no modo de produção para mostrar o stacktrace?
BKSpurgeon
@levinalex - obrigado alex. existe alguma maneira de adicionar uma string personalizada à mensagem de erro?
BKSpurgeon
62

Você pode fazer assim:

class UsersController < ApplicationController
  ## Exception Handling
  class NotActivated < StandardError
  end

  rescue_from NotActivated, :with => :not_activated

  def not_activated(exception)
    flash[:notice] = "This user is not activated."
    Event.new_event "Exception: #{exception.message}", current_user, request.remote_ip
    redirect_to "/"
  end

  def show
      // Do something that fails..
      raise NotActivated unless @user.is_activated?
  end
end

O que você está fazendo aqui é criar uma classe "NotActivated" que servirá como Exception. Usando aumento, você pode lançar "NotActivated" como uma exceção. rescue_from é a maneira de capturar uma Exceção com um método especificado (not_activated neste caso). Um exemplo bem longo, mas deve mostrar como funciona.

Muitas felicidades,
Fabian

halfdan
fonte
Isso não mostra a exceção e o rastreamento de pilha no modo de desenvolvimento e mostra a página "Desculpe, mas algo deu errado" no modo de produção.
Chirag Patel
2
A página "desculpe" é, na verdade, o manipulador de erros 500 do seu servidor da web. Verifique seu arquivo .htaccess e normalmente você o verá lá
Jeff Paquette
Talvez não seja uma resposta ao OP, mas um exemplo muito útil, obrigado!
Neil Stockbridge
11

Se você precisa de uma maneira mais fácil de fazer isso e não quer muito barulho, uma execução simples pode ser:

raise Exception.new('something bad happened!')

Isso levantará uma exceção, digamos ecome.message = something bad happened!

e então você pode resgatá-lo como está resgatando todas as outras exceções em geral.

Sambhav Sharma
fonte
Não é uma boa ideia levantar ou resgatar 'Exception' em si, tente usar StandardError ao invés. Veja mais detalhes: stackoverflow.com/questions/10048173/…
Ekamjit Singh