RubyでDSL書くときのちょっとした工夫?
ほっ・・・(意味なし) 最近、Rubyで内部DSLの設計を勉強しているkitakです。
DSLの設計でこうしたらいいんじゃね?と思ったのでご紹介。
こんなかんじのDSLを書くとする。
# coding: utf-8 class Link attr_accessor :band_width, :delay, :queue_size def initialize yield self end end # ここがDSLだよ! link = Link.new do |l| l.band_width = '100Mb' l.delay = '20ms' l.queue_size = 5 end puts link.band_width puts link.delay puts link.queue_size
インスタンスを生成して、プロパティを設定しています。 initializeメソッドではなく、 ブロックを使っているところがミソです。
設定する項目が増えたときは、こっちのほうが読みやすいと思います。
だけど、 ブロックにインスタンス自身(self)を渡さないとダメなんですよね... インスタンスを渡さずに設定できたらいいなぁと思ってたんですが、この前ひらめいたのは
instance_evalを使えばいいじゃないか!
改良したやつ
class Link def initialize(&block) self.instance_eval &block end def params [@band_width, @delay, @queue_size].each do |param| puts "#{param}" end end private def band_width(param) @band_width = param end def delay(param) @delay = param end def queue_size(param) @queue_size = param end end link = Link.new do band_width '100Mb' delay '20ms' queue_size 5 end link.params
あかん...なんかおかしいことしてる気がする。
ブロック内はメソッド呼び出しの形にしたい(@をつけて代入はしたくない)。
うーむ、もっと良い方法がありそうだ、要調査