#html #ruby-on-rails #ruby #error-handling
Вопрос:
Я думаю, что у меня есть понимание того, как around_action
работает an, в основном выполняя то, что происходит до yield
as a before_action
и что происходит после yield
as an after_action
.
Я хотел бы знать, как эффективно обрабатывать ошибки и отзывы, предоставляемые пользователю, если на этом пути произойдет что-то неправильное, поскольку yield
выполняется весь код в блоке (в данном примере index
действие контроллера), несмотря ни на что.
Как я могу отображать флэш-сообщения условно о том, была ли вызвана ошибка или было ли выполнено спасение от ошибки или нет?
Проблема: A flash[:success]
отображается даже при rescue
выполнении ошибки a (вводит в заблуждение).
контроллер:
class ReportsController
around_action :wrap_in_transaction, only: %i(index)
rescue_from FileExportError, with: :file_export_error
def index
@tickets = Ticket.all
respond_to do |format|
format.html
format.xlsx do
response.headers["Content-Disposition"] = "attachment; filename=report"
end
end
flash[:success] = "Success"
update_tickets(@tickets) # rolls back if a rescue happens
end
end
private
def wrap_in_transaction
ActiveRecord::Base.transaction do
yield
rescue FileExportError
raise ActiveRecord::Rollback
end
end
def file_export_error
flash[:danger] = t(".file_export_error")
redirect_to reports_path
end
def update_tickets(tickets)
tickets.each do |ticket|
ticket.update(status: "unpaid")
end
end
end
.xls.erb вызывает ошибку, если поврежденные данные пытаются создать файл:
@tickets.each do |ticket|
if ticket.some_data.nil?
raise FileExportError
end
sheet.add_row [ticket.user.full_name,
ticket.user.phone,
...]
Ответ №1:
(Не обращайте внимания на мой предыдущий ответ, я просматривал и неправильно понял, как вы запускали откат.)
Ваш код выполняет следующие действия:
- Загружает все билеты
- Настраивает формат ответа
- Устанавливает флэш — сообщение на успех
- Выполняет некоторые обновления записей
В какой-то момент после этого может возникнуть ошибка экспорта; это вызовет откат транзакции БД, но flash[:success]
назначение не будет откатываться, потому что это не транзакция БД. Почему бы не попробовать выполнить flash[:error]
спасательный блок вместо успеха? Или, может быть, перемещение успеха после выхода в блоке транзакций может сработать?
Комментарии:
1. Спасибо. Если я перемещаю вспышку после yeild, она отображается только после перезагрузки страницы по какой-то причине. Как бы я сделал блок аварийного спасения?
2. кроме того, установка гарантии с
redirect_to
wrap_in_transaction
помощью метода внутри приводит к ошибке «слишком много перенаправлений», несмотря на то, что она единственная, как я ее вижу. Так что я еще больше запутался.3. Я использовал
.discard
флэш-сообщение об успехе внутриrescue
блока, чтобы исправить первую проблему. Мне до сих пор не удалось придумать способ отображения флэш-сообщения без перенаправления.4. Вам, вероятно, понадобится какой-то вариант
redirect_to some_path amp;amp; return
, чтобы убедиться, что он останавливает выполнение и перенаправляет на нужный путь, но я также не уверен, что даже необходимо указывать перенаправление там, учитывая, что похоже, что вы перенаправляете на свой путь индекса (что произойдет, когда вы полностью удалите перенаправление?).