Можете ли вы условно отобразить флэш-сообщение о том, что произошло внутри блока yield в фильтре around_action?

#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:

(Не обращайте внимания на мой предыдущий ответ, я просматривал и неправильно понял, как вы запускали откат.)

Ваш код выполняет следующие действия:

  1. Загружает все билеты
  2. Настраивает формат ответа
  3. Устанавливает флэш — сообщение на успех
  4. Выполняет некоторые обновления записей

В какой-то момент после этого может возникнуть ошибка экспорта; это вызовет откат транзакции БД, но flash[:success] назначение не будет откатываться, потому что это не транзакция БД. Почему бы не попробовать выполнить flash[:error] спасательный блок вместо успеха? Или, может быть, перемещение успеха после выхода в блоке транзакций может сработать?

Комментарии:

1. Спасибо. Если я перемещаю вспышку после yeild, она отображается только после перезагрузки страницы по какой-то причине. Как бы я сделал блок аварийного спасения?

2. кроме того, установка гарантии с redirect_to wrap_in_transaction помощью метода внутри приводит к ошибке «слишком много перенаправлений», несмотря на то, что она единственная, как я ее вижу. Так что я еще больше запутался.

3. Я использовал .discard флэш-сообщение об успехе внутри rescue блока, чтобы исправить первую проблему. Мне до сих пор не удалось придумать способ отображения флэш-сообщения без перенаправления.

4. Вам, вероятно, понадобится какой-то вариант redirect_to some_path amp;amp; return , чтобы убедиться, что он останавливает выполнение и перенаправляет на нужный путь, но я также не уверен, что даже необходимо указывать перенаправление там, учитывая, что похоже, что вы перенаправляете на свой путь индекса (что произойдет, когда вы полностью удалите перенаправление?).