動的なメソッド定義

irb(main):001:0> # テスト対象のクラス
irb(main):002:0* class A
irb(main):003:1> end
=> nil
irb(main):004:0>
irb(main):005:0* # テスト対象のオブジェクト
irb(main):006:0* a = A.new
=> #<A:0x2ce93dc>
irb(main):007:0>
irb(main):008:0* # メソッド名が決まっている場合のインスタンスメソッド追加
irb(main):009:0* def a.foo
irb(main):010:1>   'foo'
irb(main):011:1> end
=> nil
irb(main):012:0> a.foo
=> "foo"
irb(main):013:0>
irb(main):014:0* a.instance_eval do
irb(main):015:1*   def bar
irb(main):016:2>     'bar'
irb(main):017:2>   end
irb(main):018:1> end
=> nil
irb(main):019:0> a.bar
=> "bar"
irb(main):020:0>
irb(main):021:0* A.class_eval do
irb(main):022:1*   def baz
irb(main):023:2>   'baz'
irb(main):024:2>   end
irb(main):025:1> end
=> nil
irb(main):026:0> a.baz
=> "baz"
irb(main):027:0>
irb(main):028:0*
irb(main):029:0* # メソッド名が決まっている場合のクラスメソッド追加
irb(main):030:0* def A.foo
irb(main):031:1>   'FOO'
irb(main):032:1> end
=> nil
irb(main):033:0> A.foo
=> "FOO"
irb(main):034:0>
irb(main):035:0* A.instance_eval do
irb(main):036:1*   def bar
irb(main):037:2>     'BAR'
irb(main):038:2>   end
irb(main):039:1> end
=> nil
irb(main):040:0> A.bar
=> "BAR"
irb(main):041:0>
irb(main):042:0* A.class_eval do
irb(main):043:1*   def self.baz
irb(main):044:2>   'BAZ'
irb(main):045:2>   end
irb(main):046:1> end
=> nil
irb(main):047:0> A.baz
=> "BAZ"
irb(main):048:0>
irb(main):049:0*
irb(main):050:0* method_name = :qux
=> :qux
irb(main):051:0>
irb(main):052:0* # メソッド名が決まっている場合のインスタンスメソッド追加
irb(main):053:0* A.class_eval do
irb(main):054:1*   define_method(method_name) { method_name.to_s }
irb(main):055:1> end
=> #<Proc:0x02961f5c@(irb):54>
irb(main):056:0> a.send(method_name)
=> "qux"
irb(main):057:0>
irb(main):058:0*
irb(main):059:0* # メソッド名が決まっていない場合のクラスメソッド追加
irb(main):060:0* m = Module.new{
irb(main):061:1*   define_method(method_name) { method_name.to_s.upcase }
irb(main):062:1> }
=> #<Module:0x2d53a84>
irb(main):063:0> A.extend(m)
=> A
irb(main):064:0> A.send(method_name)
=> "QUX"
irb(main):065:0>
irb(main):066:0* a.singleton_methods
=> ["foo", "bar"]
irb(main):067:0> A.singleton_methods
=> ["baz", "foo", "bar", "qux"]
irb(main):068:0>

A.quxも特異メソッドになるんですね。


ちなみにfoo,bar,bazの後はRFCで決まっているそうです(ウソ)
http://www.puni.net/~mimori/rfc/rfc3092.txt