Module#define_methodを抽象化する話
Jay Fields' Thoughts: Ruby: Dynamically Define Method
たとえば、インスタンス変数にメソッド名のシンボルを格納するような一連のメソッドがあるとする。
def failure self.state = :failure end def error self.state = :error end def success self.state = :success end
これらはModule#define_methodでまとめられる。
[:failure, :error, :success].each do |method| define_method method do self.state = method end end
しかし、このままだと読みづらいからModule#def_eachを定義して抽象化する。*1
class Module def def_each(*method_names, &block) method_names.each do |method_name| define_method method_name do instance_exec method_name, &block end end end end
Module#def_eachを使うとさきほどのメソッド定義はこのように読みやすくなる。
def_each :failure, :error, :success do |method_name| self.state = method_name end
まあ、ぶっちゃけ黒魔術っぽい記述を具象クラスからは削除して、抽象化したメソッドを使えば読みやすくなるよーって話だ。readabilityのためなら、既存のクラスにメソッドを追加することくらいいとわない。納得。
*1:原文だとClass#def_eachだがModule#def_eachにすべき。