Refinementsはレキシカルスコープという説明をよく聞くけど、どこにコードが書かれているかというよりはusingを呼んだ後の環境で評価されるかどうかというのが重要。なのでコードの字面でRefinementsで定義したメソッドの呼び出しがusingより前に書かれていても、先にusingの方が評価されていれば呼び出せる。
Refinements are only active within a scope after the call to using.
https://docs.ruby-lang.org/en/2.5.0/syntax/refinements_rdoc.html
その1. BEGINの中でusing
BEGINでusingを使うとどのコードよりも先にusingが実行されるため先頭行でusingを書いたのと同じように働く。
hi
# hi
BEGIN {
using Module.new {
refine(Object) do
def hi
puts "hi"
end
end
}
}
その10. bindingを使う
evalの第二引数にusingが効いた環境のbindingを渡すとusingで定義したメソッドが使える。
def greeting(b)
eval('hi', b)
end
using Module.new {
refine(Object) do
def hi
puts "hi"
end
end
}
greeting(binding)
Binding#evalしてもよし。
def greeting(b)
b.eval('hi')
end
using Module.new {
refine(Object) do
def hi
puts "hi"
end
end
}
greeting(binding)
10ないじゃん
"10".to_i(2)
# => 2