如何让 Ruby 2.1.5 报告对象的 class 缺少方法错误?

How can I get Ruby 2.1.5 to report an object's class for a missing method error?

这一行:

@page = @page.launch_profile(@profile_name)

导致此错误:

undefined method `launch_profile' for #<Object:0x007f9013d785e8> (NoMethodError)

如果我在抱怨的电话前添加 puts "Page = #{@page} "{@page.class}",我会得到

Page = #<OwnProfilePage:0x007f9013bf5e78> OwnProfilePage

奇怪的是,在命令行上,相同版本的 Ruby (2.1.5) 执行此操作:

$ ruby -le 'class Dog; end; Dog.new.foo'
-e:1:in `<main>': undefined method `foo' for #<Dog:0x007fb64120c6d8> (NoMethodError)

所以我知道它通常有效。

我已经尝试将 method_missing() 方法添加到 Object,但它没有任何影响,所以我认为其他人在其他地方正在猴子修补或覆盖或以其他方式破坏元数据.我什至修补了 NoMethodError.new() 以打印堆栈跟踪以尝试找到错误代码。

此外,当可能有如此多的巫术和其他构思不佳的全球变化废话在遥远的地方发生时,是否有一个合理的通用方法来确定 Ruby 系统的哪一部分在做什么?随机宝石? (在另一种情况下,'fail' 开始报告 previous rescued exception 的消息,而不是我提供的字符串。)

好的,我知道是怎么回事了:

它是 calabash-android 的 ABase class,它的 method_missing 'helpfully' 委托给它的 world object,它也不知道我的方法(毫不奇怪)。不幸的是,当 his/her 令人惊讶的实现细节失败时,它的作者没有考虑捕获异常,所以它报告的不是我的页面 object 而是世界 object 并使 Ruby 看起来很糟糕。

如果我仔细查看我的日志记录的 hexagibberish,我会注意到它不是 Ruby 误报了我的页面 object 的 class,而是正确地报告了一个完全不同的object(虽然 object 的 class 不是 Object,但 Object+Test::Unit::Assertions+half+a+million+other+mixins 会更快地告诉我它报告了错误东西)。

我已经将 method_missing 的 body 包装在一个 try/catch 中,它报告了真实的 object 并且还提到 world 中的任何内容都不知道关于它。

这是我不喜欢魔法的主要原因之一:人们通常无法提供正确的诊断。另一个主要原因是因为用于透明地实现令人惊讶的行为的魔法是邪恶的。