The example below creates a refinement module which adds a method to instances of Integer. In the Test class, we bring it into scope by declaring using Refinements. Next, we create an instance method using def_delegators named Test#xxx that calls @k.xxx, which should resolve to the refinement method we added to Integer. Finally, we "manually" create essentially the same method, this time named yyy, but we define it "manually" without using def_delegators.
require "forwardable"
module Refinements
refine Integer do
def xxx
:xxx
end
end
end
class Test
using Refinements
extend Forwardable
def_delegators :@k, :xxx
def initialize
@k = 100
end
def yyy
@k.xxx
end
endThe test snippet below demonstrates ordinary methods (like yyy) inherit the refinement methods from the scope in which they are defined. However, methods defined by class_eval or module_eval do not inherit the refinements which are in the lexical scope of the class_eval caller.
Instead, methods defined by class_eval or module_eval inherit the refinements from the call site of class_eval, which would be Forwardable, not Test. Since module Forwardable; ...; end does not have a using Refinements declaration, our xxx method doesn't see them.
p Test.new.yyy #=> :xxx
p Test.new.xxx #=> undefined method `xxx` for 100:Fixnum (NoMethodError)