StandardError重定向到页面

时间:2016-05-06 23:28:41

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

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

该应用可能会遇到“未找到结果”等错误,然后我提出了标准错误。

我想将用户重定向到错误页面并通知他们但是我不能这样做因为它不是控制器,所以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

3 个答案:

答案 0 :(得分:1)

你应该创建另一个错误类,例如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

答案 1 :(得分:0)

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

如果由于某种原因这不是一个选项,您可以检查用户是否在任何相关控制器中有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有东西的时候警告用户。

答案 2 :(得分:0)

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

# 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