「ERB で Binding のかわりに Hash を使う」について

kwatchさんの日記より。


ERB で Binding のかわりに Hash を使う
http://d.hatena.ne.jp/kwatch/20080609/1213029122


ごまかしで、ローカル変数「っぽく」書ける案を思いついたので書いてみる。


いったん代入されてしまえば、ローカル変数の参照のほうが優先されるのでこれでいい…筈。
initialize、_context、_erboutっていう名前に触らずに暮らすと平穏だろう、たぶん。
Erubis::Eruby#result()の挙動はちゃんと調べなかったけど、Hash渡せばHashを展開してくれたように使える筈だ。

筈とか多分とかばっかりだな。

require 'erb'

class ERB
  
  class Sandbox #:nodoc:
    
    def initialize(h={})
      (class << self ; self ; end).class_eval do
        h.each{|k, v| define_method(k){v} }
      end
    end
    
    def _context
      binding()
    end
    
  end #class Sandbox
  
  def evaluate(h={})
    obj = Sandbox.new(h)
    result obj._context
  end
  
  # redefine ERB#result
  org = instance_method(:result)
  define_method :result do |*args|
    if args.empty? || args.first.kind_of?(Binding)
      org.bind(self).call(*args)
    else
      evaluate(*args)
    end
  end
  
end #class ERB