あなたの Ruby コードを添削します 【第 3 回】 dbf.rb を参考にして、DSL を処理する部分を書いてるんだけど、ネストしたモジュールの下に DSL の記述を持ってくると、外部で定義したクラスが見えなくてちょっとハマる。1.8 だと動くのが何とも。
RUBY_DESCRIPTION # => "ruby 1.8.7 (2009-06-12 patchlevel 174) [i486-linux]" class C class << self def m(&b) Class.new(self) do |c| c.class_eval(&b) end end end end C1 = C.m{} C2 = C.m{ self # => #<Class:0xb7c9d6ac> C1 # => C1 } module M module M1 C3 = C.m{} end module M2 include M1 C4 = C.m{ self # => #<Class:0xb7c9d0a8> C3 # => M::M1::C3 } end end
C.m が PackedStruct.define というイメージ。1.8 だとこれでうまくいくんだけど、
RUBY_DESCRIPTION # => "ruby 1.9.2dev (2009-08-11 trunk 24495) [i686-linux]" class C class << self def m(&b) Class.new(self) do |c| c.class_eval(&b) end end end end C1 = C.m{} C2 = C.m{ self # => #<Class:0x98d184c> C1 # => C1 } module M module M1 C3 = C.m{} end module M2 include M1 C3 # => M::M1::C3 C4 = C.m{ self # => #<Class:0x98d0ed8> C3 # => } end end # ~> -:29:in `block in <module:M2>': uninitialized constant #<Class:0x8422004>::C3 (NameError) # ~> from -:7:in `class_eval' # ~> from -:7:in `block in m' # ~> from -:6:in `initialize' # ~> from -:6:in `new' # ~> from -:6:in `m' # ~> from -:27:in `<module:M2>' # ~> from -:24:in `<module:M>' # ~> from -:19:in `<main>'
1.9 だとうまくいかない。だいぶ悩んだけど、
- c.class_eval(&b) + c.class_eval{b.call}
に変えたらいけた。こうすると C.m{} 内の self が main やら M::M2 になってうまくいくみたい。まだ理解しきれてないけど、とりあえず日記書くと色々解決する。
追記: と思ったら、これでは C のクラスメソッドとして用意してる DSL 用のメソッドが見えないぉ。目的を見失ってるぉ。