RubyでDSLを書く

Rackのコードを読んでたらDSL使ってたのでその部分. instance_evalを使ってBuilderクラス内でblockを実行するようにしている.

つまり以下のプログラムは,Builderのインスタンス内で呼ばれたことになってる.

  map '/' do
    {
      'Content-Type' => 'text/plain',
      'status' => 200,
      'body' => 'this is root!'
    }
  end
class Builder
  def initialize(&block)
    instance_eval(&block) if block_given?
  end

  def map(path, &block)
    set(:get, path, block)
  end

  def get(path)
    key = [:get, path]
    route_table[key].call
  end

  private

  def set(name, path, block)
    key = [name, path]
    route_table[key] = block
  end

  def route_table
    @route_table ||= {}
  end
end

app = Builder.new do
  map '/' do
    {
      'Content-Type' => 'text/plain',
      'status' => 200,
      'body' => 'this is root!'
    }
  end
end

p app.get('/')
# => {"Content-Type"=>"text/plain", "status"=>200, "body"=>"this is root!"}

まとめ

最高の夏

参考

http://ref.xaio.jp/ruby/classes/object/instance_eval