Ruby NoMethodError 异常默认调用 #inspect

The*_*Log 5 ruby puppeteer

我在 Ruby 中发现了一个奇怪的问题,我不太确定这是一个问题还是最近 Ruby 版本中引入的功能。

基本上,当我们调用未定义的方法时,我们会收到undefined methodRuby 中预期的错误。问题是它还调用inspect并打印出对象及其所有属性/值。如果我的对象是一个复杂的对象,那么需要很长时间才能完成所有内容的打印,并且很多时候它会导致我的本地 Rails 服务器挂起,特别是当有一个属性保存二进制数据时。这个问题似乎不会发生在 Ruby 2.6 上,但 Ruby >= 2.7 上。

对于简单的对象,这不是问题,但我特别遇到这个 gem: 的问题puppeteer-ruby。这个 gem 中的每个对象都有很多属性和依赖项。

这是一个示例,我在 IRB 中使用不同的 Ruby 版本运行以下代码并得到不同的异常:

require 'puppeteer-ruby'
browser = Puppeteer.launch(headless: true)
browser.foo
Run Code Online (Sandbox Code Playgroud)

红宝石2.6.6

NoMethodError: undefined method `foo' for #<Puppeteer::Browser:0x00007fce2d553b30>
Did you mean?  for
Run Code Online (Sandbox Code Playgroud)

红宝石3.0.0

(irb):9:in `<main>': undefined method `foo' for #<Puppeteer::Browser:0x00007f9300550740 @ignore_https_errors=false, @default_viewport=#<Puppeteer::Viewport:0x00007f92ffbf8e90 @width=800, @height=600, @device_scale_factor=1.0, @is_mobile=false, @has_touch=false, @is_landscape=false>, @process=#<Puppeteer::BrowserRunner::BrowserProcess:0x00007f92fc5ae448 @spawnargs=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "--disable-background-networking", "--enable-features=NetworkService,NetworkServiceInProcess", "--disable-background-timer-throttling", "--disable-backgrounding-occluded-windows", "--disable-breakpad", "--disable-client-side-phishing-detection", "--disable-component-extensions-with-background-pages", "--disable-default-apps", "--disable-dev-shm-usage", "--disable-extensions", "--disable-features=Translate", "--disable-hang-monitor", "--disable-ipc-flooding-protection", "--disable-popup-blocking", "--disable-prompt-on-repost", "--disable-renderer-backgrounding", "--disable-sync", "--force-color-profile=srgb", "--metrics-recording-only", "--no-first-run", "--enable-automation", "--password-store=basic", "--use-mock-keychain", "--enable-blink-features=IdleDetection", "--headless", "--hide-scrollbars", "--mute-audio", "about:blank", "--remote-debugging-port=0", "--user-data-dir=/var/folders/qn/kx4kb8xx5x13gx77yy2q56fr0000gn/T/puppeteer_dev_chrome_profile-20210910-25051-m7mnxb"], @stdout=#<IO:fd 24>, @stderr=#<IO:fd 26>,......very long text after this..
Run Code Online (Sandbox Code Playgroud)

roo*_*roo 2

这很有趣 -inspect总是打印内部变量。

归咎于最后一次更改是inspect在 9 年前:rb_object_inspect#704

使用 2.6 的简单脚本:

> docker run -it ruby:2.6.6-alpine sh
#> ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux-musl]
#> irb
irb(main):001:0> class Foo; def initialize(message); @message = message; end; end
=> :initialize
irb(main):002:0> Foo.new('hello').foo
NoMethodError (undefined method `foo' for #<Foo:0x00007f35e20e0280 @message="hello">)
Did you mean?  for
Run Code Online (Sandbox Code Playgroud)

尽管查看源代码,Puppeteer::Browser他们似乎在大约 2 年前更改为浏览器的纯 ruby​​ 实现。当他们这样做时,他们向班级介绍了很多伊瓦尔。也许您使用的版本在将 ruby​​ 从 2.6 更新到 3.0 期间发生了变化?

一个简单的修复方法是inspect在 上进行猴子补丁Puppeteer::Browser,或者向维护者发送 PR - 看起来该项目在 GitHub 上很活跃。