一時的にメソッドをすり替える
メタプログラミング ruby を読みました。よくまとまっていて、いい本だなあと思いました。
個人的にはあんまり ruby で実行時にメソッドやクラス、モジュールを操作することはメタじゃないと思っているんですが…それはうさつのとして…折角なのでメタっぽい話を一つ。
オブジェクトのメソッドを一時的に別の物にすり替えたい、という時があります。
例えば ActiveRecord の ActiveRecord::Base#inspect は、実装に ActiveRecord::Base#attribute_for_inspect を利用しているのですが、この attribute_for_inspect は、50 文字より長い文字列を省略してしまいます。irb を使っている時等は、だらだらとひたすらに長い文字列が出ても困るのでありがたいのですが、それでは困ることも当然あります。
テストなんかのことを考えると、割合こういう状況は多いんじゃないかな、と思います。C++ だと、そのまんまの物として sexyhook とかがありますね。
何はともあれ、すりかえてみましょう。話は簡単で、特異クラスにメソッドを足したり消したりすればいいのです。
def hijack(obj, name, method) class<<obj;self end.instance_eval{ define_method(name, method) yield(obj) remove_method(name) } end class C; def f; p :f end end c = C.new c.f # => :f hijack(c, :f, proc { p :g }){|o| o.f # => :g } c.f # => :f
やったー。
ところでこれ、ActiveSupport になら何か既にありそうな気も。知らないですけど…