ruby-on-railsrubyrefinements

Why does the Rails executor not recognize refinements on Kernel?


update that's burried in an answer comment below: the problem was happening in ruby 2.7, this is fixed in ruby 3


I discovered that if code is run within a Rails executor, refinements are not recognized. It doesn't seem to be because of blocks or procs, which was my only guess. Here's some demo code:

require './config/environment.rb'

module ExammpleRefinement
  refine ::Kernel do
    def say_hello
      puts "hello"
    end
  end
end

using ExammpleRefinement

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

run with ruby example.rb (can't do it with rails runner, because starting in rails 7 it wraps the entire script in an executor, so it ruins the experiment)

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 2.7


Solution

  • I wasn't able to reproduce the behaviour with the exact test file you provided (in my test it failed immediately after requiring config/environment, regardless of executor wrapping), but I imagine I've tracked it to the same cause anyway:

    During application initialization, likely due to use of EventedFileUpdateChecker, Kernel gets prepended by ForkTracker.

    Presumably (and somewhat understandably), refinements doesn't like that.