読者です 読者をやめる 読者になる 読者になる

Ruby でメソッドを薄くラップする

Ruby

みたいな機能が欲しかったので書いてみた。

[コード]

module MethodWrapper
    def wrap name, &block
        prepend(Module.new do
            define_method name do
                super_ = proc { super() }
                Object.new.instance_eval do
                    define_singleton_method :super_ do
                        super_.()
                    end
                    instance_eval &block
                end
            end
        end)
    end

    def self.included klass
        klass.extend self
    end
end


class X
    include MethodWrapper

    def homu
        p :homu
    end

    # 第一引数にラップしたいメソッド名を渡して、処理するメソッドの内容をブロックで定義する
    wrap :homu do
        p "wrapped method"
        # ラップした元のメソッドを呼び出す場合は #super_ を呼び出す
        super_
    end
end

# ラップしたメソッドを呼び出す
X.new.homu

[出力]

"wrapped method"
:homu

ブロック内で元のメソッドを呼び出したかったので prependmodule を使って super を呼びだせるようにしています。
ただし、ブロック内から直接 suepr を呼ぶことはできないのでちょっとごまかしています。
ここら辺どうにかしたかったんですが、無理ぽい感じ…。
しかし、結果的にすごいコードになってしまったな、Ruby の闇を感じる。