为何Rails Executor在Ruby2.7中无法识别Kernel的Refinements?
Rails Executor中Ruby Refinements失效问题(Ruby 2.7专属)
在Ruby 2.7版本中存在一个版本缺陷:已通过using启用的Refinements,在普通代码、常规代码块、Proc中都能正常生效,但运行在Rails Executor的wrap块内时会失效。该问题已在Ruby 3及以上版本中修复。
复现代码
require './config/environment.rb' module ExampleRefinement refine ::Kernel do def say_hello puts "hello" end end end using ExampleRefinement puts "alone" say_hello puts "block" loop do say_hello break end puts "proc" Proc.new{say_hello}.call puts "rails executor" ::Rails.application.executor.wrap do say_hello end
注:原代码中
ExammpleRefinement为拼写失误,已修正为ExampleRefinement,不影响问题复现
运行方式
使用以下命令执行脚本,禁止使用rails runner——从Rails 7开始,rails runner会将整个脚本包裹在Executor中,无法复现差异:
ruby example.rb
运行输出
alone hello block hello proc hello rails executor Traceback (most recent call last): 2: from example.rb:25:in `<main>' 1: from ....rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-7.0.4/lib/active_support/execution_wrapper.rb:92:in `wrap' scripts/example.rb:26:in `block in <main>': undefined local variable or method `say_hello' for main:Object (NameError)
解决方案
- 彻底解决:升级到Ruby 3及以上版本,该版本已修复此缺陷
- 临时替代(不推荐):若无法升级Ruby,可将Refinements逻辑替换为全局方法定义(会污染全局命名空间),或调整代码结构,避免在Executor块内依赖Refinements
内容的提问来源于stack exchange,提问作者John Bachir
相关产品推荐
相关产品推荐

