【问题标题】:Catching Same Exception between Methods/ Classes在方法/类之间捕获相同的异常
【发布时间】:2016-05-04 07:22:49
【问题描述】:

我正在调用一个函数来从源类型中获取数据,因此我创建了一个名为 FileReader 的超类和几个类,每个类用于 FTP、SFTP、Google Drive 等。它们中的每一个都将继承并实现一个 @ 987654322@ 功能。

我想捕获gems返回的异常,这样我们就不会将外部因素作为错误报告报告给Rollbar,所以我们拯救异常并在找不到文件时向用户返回正确的消息,请求定时等。救援块在超类上,因为像 SocketError、EOFError 这样的异常在所有子类中都很常见,所以我试图让我的代码保持干燥。

class FileReader

  def get_data
    nil
  end

  def read
    data = nil
    begin
      data = get_data
    rescue EOFError => e
      # return error message
    rescue SocketError => e
      # return error message
    rescue OpenURI::HTTPError => e
      # return error message
    rescue Net::FTPPermError => e
      # return error message
    rescue Net::SFTP::StatusException => e
      # return error message
    rescue Errno::ETIMEDOUT => e
      # return error message
    rescue Exception => e
      puts e.message
      puts e.backtrace.join("\n")
      Rollbar.error(e, :source => self)
      # return error message
    end
    return data
  end

end

FtpFileReader继承FileReader类实现get_data函数。

class FtpFileReader < FileReader

  def get_data
    # connect to ftp, get file, return data
    # no begin and rescue block here
  end

end

我的 read 方法是从我的 Rails 模型中调用的。

但是捕捉这样的异常对我来说很棘手。 调用方法read 捕获了这个异常,如果我在其中实现了一个救援块,FileReader#get_data 方法是否也捕获了相同的异常?

我应该在 FileReader get_data 方法而不是 read 中捕获这些异常吗?或者我应该在子类本身中捕获这些特定异常并在子类中的每个get_data 方法中返回错误消息?最终要捕获的类会更大,但会重复 EOFError,SocketError 不会那么枯燥。在这种情况下处理异常的最佳方法是什么?

【问题讨论】:

  • 为什么你认为错误应该被你的一个子句捕获(除了 catch all rescue Exception 子句)
  • @FrederickCheung 你是什么意思?
  • 我的意思是为什么你认为这个错误不应该出现在 rescue Exception 位?
  • 您得到的是 Net::FTPTempError 而不是 Net::FTPPermError。您不像其他特殊情况那样处理 Net::FTPTempError ,它在 rescue Exception =&gt; e 中处理
  • @FrederickCheung 捕捉不同类型的错误信息给用户,以便他们在想要获取数据时知道是什么问题,例如 FTP 身份验证失败、找不到文件等。通用异常救援位是为了捕捉NilClass错误等潜在的bug。

标签: ruby-on-rails ruby exception


【解决方案1】:

首先,永远不要从Exception 中解脱出来(除非你正在反加注,即便如此,问问自己为什么要这么做)。而是从StandardError 救援。阅读它here

我将仅在这些子类中为特定于子类的错误定义rescues,以便可以将特定逻辑完全隔离到相关子类中。您可以按照您的建议执行此操作,方法是将特定错误捕获移动到 get_data 方法。但是您可能会考虑定义一个新方法,以便您可以使用非救援方法(可能只是出于调试目的,或者来自您希望以不同方式处理错误的另一个控制器)。这是我考虑的一种方式:

class FtpFileReader < FileReader
  def get_data
    get_data!
  rescue Net::FTPPermErro => e
    # return error message
  end

  def get_data!
    # do stuff
  end
end

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 2011-02-12
    • 2014-11-24
    相关资源
    最近更新 更多