method_missingをdefine_methodに置き換える話
Jay Fields' Thoughts: Ruby: Replace method_missing with dynamic method definitions
Decoratorオブジェクトはメソッドをコンストラクタで指定されたオブジェクトに丸投げする委譲オブジェクトだ。
そこに存在しないメソッドを投げてみると…
method_missingを使って実装されたやつはこんな感じでエラーメッセージにDecoratorの文字すら出てこないからデバッグが困難だ。m9(^Д^)プギャー
class Decorator def initialize(subject) @subject = subject end def method_missing(sym, *args, &block) @subject.send sym, *args, &block end end d = Decorator.new [1] d.length # => 1 d.not_exist # ~> -:7:in `method_missing': undefined method `not_exist' for [1]:Array (NoMethodError) # ~> from -:13:in `<main>'
method_missingではなくてコンストラクタに渡された時点のメソッドをdefine_methodで動的に登録するとエラーメッセージにDecoratorが出てくる。やっぱ俺こっちのが好きだ。
class Decorator def initialize(subject) subject.public_methods(false).each do |meth| (class << self; self; end).class_eval do define_method meth do |*args| subject.send meth, *args end end end end end d = Decorator.new [1] d.length # => 1 d.not_exist # ~> -:15:in `<main>': undefined method `not_exist' for [1]:Decorator (NoMethodError)