Как мне вызвать исключение в Rails, чтобы оно вело себя как другие исключения Rails?

92

Я хотел бы вызвать исключение, чтобы оно делало то же самое, что и обычное исключение Rails. В частности, покажите исключение и трассировку стека в режиме разработки и покажите страницу «К сожалению, что-то пошло не так» в рабочем режиме.

Я пробовал следующее:

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

Но он просто записывает "ERROR signing up, group missing!"в файл development.log

Чираг Патель
источник
2
сообщение об ошибке, которое вы опубликовали, похоже, не связано с этим исключением (это другое сообщение), это действительно то, что вы видите?
levinalex

Ответы:

140

Ничего особенного делать не надо, просто должно работать.

Когда у меня есть новое приложение rails с этим контроллером:

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

и перейти к http://127.0.0.1:3000/foo/

Я вижу исключение с трассировкой стека.

Вы можете не увидеть всю трассировку стека в журнале консоли, потому что Rails (начиная с 2.3) фильтрует строки из трассировки стека, поступающие из самого фреймворка.

Смотрите config/initializers/backtrace_silencers.rbв своем проекте Rails

левиналекс
источник
2
Отличный, лаконичный ответ.
rcd 05
1
Ссылка на skitch (видна исключение с трассировкой стека) больше не работает
Асаф
@levinalex будет ли это безопасно в производственном режиме показывать трассировку стека?
BKSpurgeon
@levinalex - спасибо, Алекс. есть ли способ добавить настраиваемую строку в сообщение об ошибке?
BKSpurgeon
63

Сделать это можно так:

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

Здесь вы создаете класс NotActivated, который будет служить исключением. Используя рейз, вы можете выбросить NotActivated как исключение. rescue_from - это способ перехвата исключения с помощью указанного метода (в данном случае not_activated). Довольно длинный пример, но он должен показать вам, как это работает.

С наилучшими пожеланиями,
Фабиан

Halfdan
источник
Это не отображает исключение и трассировку стека в режиме разработки и не отображает страницу «Приносим извинения, но что-то пошло не так» в рабочем режиме.
Чираг Патель
2
Страница «извините» на самом деле является обработчиком ошибок 500 вашего веб-сервера. Проверьте свой файл .htaccess, и вы обычно увидите его там
Джефф Пакетт
Возможно, это не ответ на OP, но очень полезный пример, спасибо!
Нил Стокбридж
12

Если вам нужен более простой способ сделать это и не нужно много суеты, простое выполнение может быть таким:

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

Это вызовет исключение, скажем, eсe.message = something bad happened!

а затем вы можете спасти его, как и все остальные исключения в целом.

Самбхав Шарма
источник
Не рекомендуется вызывать или спасать само исключение, попробуйте вместо этого использовать StandardError. См. Подробности: stackoverflow.com/questions/10048173/…
Экамджит Сингх