Ruby の refinements の落とし穴

Ruby の refinements の落とし穴

refinements を使おうとしたらちょっとつらいことになりました。 さて、refinements は using を定義したあとで有効になります。

class X

end

module Test
    refine X do
        def homu
            "homu"
        end
    end
end

# using 以降で X.homu が使えるようになる
using Test

X.new.homu
# => "homu"

しかし、次のように using 以前のメソッドからアクセスしようとするとエラーになってしまいます。

# ここで refine で定義したメソッドにアクセスしたい
def call_homu obj
    obj.homu
end

class X

end

module Test
    refine X do
        def homu
            "homu"
        end
    end
end

using Test

call_homu X.new
# error: undefined method `homu

同様の理由で X.new.respond_to? :homufalse になったり、X.new.send(:homu) がエラーになってメソッドを呼ぶことができなかったりします。 #send#method が使えないのはちょっと不便ですね…。

refinements で #to_proc を定義してもブロックに渡せない

一番困ったのはこれ。 refinements で #to_proc を定義し、ブロックに渡そうとしても内部で #to_proc を使うことができずにエラーになってしまいます。

class X

end

module Test
    refine X do
        def to_proc
            Proc.new { "to_proc" }
        end
    end
end

using Test

def method_with_block &block
    block[]
end

method_with_block &X.new
# => error: super: no superclass method `to_proc

一応、method_with_block &X.new.to_proc というように明示的に #to_proc を渡せば回避することはできるんですが、なんかもにょる。