【问题标题】:Why can't I rescue this custom error defined inside another class?为什么我不能挽救在另一个类中定义的这个自定义错误?
【发布时间】:2020-11-05 20:21:23
【问题描述】:

我正在使用 Rails 6。我在引发它的类中定义了一个错误类:

class MyClass < ApplicationRecord
  ...

  class CustomError < StandardError
    attr_reader :param

    def initialize(param)
      @param = param
    end
  end
end

我尝试在客户端代码中拯救它,但这并没有抓住它:

rescue MyClass::CustomError => e

另一方面,这在CustomError 上引发了uninitialized constant,正如我所期望的那样:

rescue CustomError => e

这个怎么样?

rescue MyClass::CustomError => e
  raise unless e.instance_of? MyClass::CustomError
  # do some real error handling
  ...
end

instance_of? 无法识别错误并重新引发。

我什至尝试过:

class MyClass < ApplicationRecord
  ...
end

class MyClass::CustomError < StandardError
  attr_reader :para
  def initialize(param)
    @param = param
  end
end

这样也好。

已经起作用的两件事都是代码异味:

  1. 在包含类之外定义错误,没有命名空间

  2. 修复一般错误:rescue =&gt; e

它在 MiniTest 中也可以正常工作:

e = assert_raises(MyClass::CustomError) do
  ...
end

感觉就像错误类名 CustomError 根本没有解析为应用程序代码中的 MyClass::CustomError,但客户端代码需要包含类名来解析类。

虽然我只是在做一些有点天真/愚蠢的事情,但更有可能!

附加信息:

  • Ruby 2.7.1
  • Rails 6.0.3.3
  • 引发错误的类和处理错误的类都是模型类(有点不寻常)
  • 引发错误的运行时类是MyClass 的子代:MyChild &lt; MyClass &lt; ActiveRecord(也很不寻常)

【问题讨论】:

  • 使用您共享的错误定义 rescue MyClass::CustomError =&gt; e 应该会捕获错误。你确定你的代码会引发它吗?
  • 感谢康斯坦丁。当我发现一般错误并输出e.class 时,我得到MyError。所以是的。但是我应该看到MyClass::CustomError 吗?
  • 刚刚解决了康斯坦丁。我不得不删除我的 Bootsnap 缓存。我不知道如何,但您的反馈提供了我需要的线索。谢谢!

标签: ruby ruby-on-rails-6


【解决方案1】:

对于不知道的人,Rails 4.2 添加了 Spring,它在您终止应用程序时将应用程序保留在内存中(以加快启动时间),Rails 5.2 添加了 Bootsnap,它缓存优化的代码。它们中的任何一个都可以保留未更改的代码,并且因为奇怪的错误。

其中一个刚刚咬了我一口。似乎 Bootsnap 引发了错误,但没有使其在 MyClass 之外可见。删除缓存就解决了:

rm -rf tmp/cache/bootsnap-compile-cache/
rm tmp/cache/bootsnap-load-path-cache

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多