【问题标题】:StandardError redirect to page标准错误重定向到页面
【发布时间】:2016-09-02 03:24:27
【问题描述】:

我收到了另一个开发人员参与的项目,没有留下任何文档。该代码从购物网站获取一些购买,查找价格并通知用户。

应用程序可能会遇到“未找到结果”等错误,然后我会引发标准错误。

我想将用户重定向到错误页面并通知他们,但我不能这样做,因为它不是控制器,所以redirect_to 选项不起作用。

services/purchase_checker.rb 每小时调用一次:

      def call
        user.transaction do
          store_purchase
          if better_purchase?
            update_purchase
          end
        end
      rescue MyError=> e
        store_error(e)
      end



def store_error(error)
    user.check_errors.create!(error_type: error.class.name, message: error.message)
  end

服务/my_error.rb:

class MyError< StandardError

  def initialize(error_type, error_message)
    super(error_message)
    @error_type = error_type
  end

  attr_reader :error_type

end

服务/purchase_fetcher.rb:

def parse_result_page
    raise purchase_form_page.error if purchase_form_page.error.present?
    offer = purchase_page.map{|proposal_section| 
            propose(proposal_section, purchase) }
                            .min_by(&:price)

    offer or raise MyError.new("No results", "No results could be found")
  end

【问题讨论】:

  • 您可以发布控制器操作以及调用 PurchaseChecker#call 的位置吗?
  • 它被一个activejob调用
  • 您的目标不清楚:如果作业每小时运行一次,您建议在请求/响应周期的哪个位置重定向用户?
  • 好的,现在看到下面的 cmets 是在初始搜索之后...
  • 在用户进行搜索后第一次执行。如果没有找到结果,它应该通知他。如果是的话,每小时都会通知他更优惠的价格...抱歉不清楚,英语不是我的语言

标签: ruby-on-rails ruby model-view-controller error-handling


【解决方案1】:

你应该创建另一个 err 类,例如NotFoundError:

offer or raise NotFoundError.new("No results", "No results could be found")

然后在你的控制器中:

begin
  parse_result_page
rescue NotFoundError => e
  redirect_to err_page, :notice => e.message
end

【讨论】:

  • 我没有这个对象的控制器。该错误在另一个对象中引发。因为它不是控制器,所以我不能使用重定向
  • 如果你不想通知用户,那么你不应该使用后台作业,因为它是异步的,你无法及时得到反馈
  • 它在用户搜索后第一次执行..然后它应该通知他没有结果
【解决方案2】:

由于这是在作业中运行,通知用户的最佳方式是通过电子邮件或其他一些异步通知方法。当检测到错误时,会发送一封电子邮件。

如果由于某种原因这不是一个选项,您可以检查用户是否在任何相关控制器中拥有check_errors。查看发现错误时调用的store_error(error) 方法,似乎它正在数据库中创建一条新记录来记录错误。您应该能够检查用户是否通过user.check_errors 关系记录了任何错误。

你可以这样做,例如:

class SomeController < ActionController::Base
  # ...
  before_action :redirect_if_check_errors

  # ...

  def redirect_if_check_errors
    # Assuming you're using Devise or something similar
    if current_user && current_user.check_errors.exists?
      redirect_to some_error_page_you_create_for_this_path
    end
  end
end

这将在SomeController 的每个操作中检查这些错误,并将用户重定向到您应该创建的错误页面,您可以在其中呈现user.check_errors 关系中的错误。

有多种方法可以做到这一点,但如果您想主动通知用户,我仍然认为从 Job 发送电子邮件是一个更好的选择。或者也许添加一个界面元素,例如,当user.check_errors 有东西时向用户发出警告。

【讨论】:

    【解决方案3】:

    我建议您同步执行此操作,以便响应可以直接在请求/响应周期中发生。也许是这样的:

    # controller

    def search
      # do your searching
      # ...
      if search_results.blank?
        # call model method, but do it synchrously
        purchase_check = PurchaseChecker.call
      end
    
      if purchase_check.is_a?(MyError) # Check if it's your error
        redirect_to(some_path, flash: { warning: "Warn them"})
      end
    end
    

    # model, say PurchaseChecker

    def call
      # do your code
    rescue MyError => e
      store_error(e)
      e # return the error so that the controller can do something with it
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-16
      • 1970-01-01
      • 2012-05-26
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多