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
end
The 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)