まずそのままだと警告が出る。prependは Ruby 3.2 から refine 内で使えなくなるので import_methods を使うようにとのこと。 warning: Refinement#prepend is deprecated and will be removed in Ruby 3.2
通らない方は Ruby で書かれたコードじゃないとあかんよという例外が出る。import_methods': Can't import method which is not defined with Ruby code: TestRefinement::TestImport::B#bar (ArgumentError)。
TL;DR
何についてか / About
ref:
経緯 / History
warning: Refinement#prepend is deprecated and will be removed in Ruby 3.2
import_methods': Can't import method which is not defined with Ruby code: TestRefinement::TestImport::B#bar (ArgumentError)
。https://github.com/ruby/ruby/blob/65122d09d515c9183e643d5f7f31d24251b149ed/eval.c#L1628-L1630 を見ると
VM_METHOD_TYPE_ISEQ
というメソッド種別みたいな物で分岐している。 https://github.com/ruby/ruby/blob/65122d09d515c9183e643d5f7f31d24251b149ed/method.h#L109-L124 に定義が合って、Ruby で書かれたコードというのはこの形になるらしい。VM_METHOD_TYPE_ALIAS
、define_method はVM_METHOD_TYPE_BMETHOD
になるっぽい。てっきり自分がRubyで書いているコードをaliasしたりブロック渡しで定義しても内部で同じ様な扱いになってるんだろうと思ってたけど、フィールドとか結構違うみたいで難しいんだなぁという小並感。(何も考えず単純に分岐広げるとSEGVする)。10年以上使ってて初めて知った~