ERB で Binding のかわりに Hash を使う
class ERB def result_hash(hash) b = binding hash.each {|k,v| eval "#{k} = %Q[#{v}]", b} result b end end puts ERB.new('<%= example %>').result_hash(:example => 'foo')ERB で引数の hash を展開して欲しい - #生存戦略 、それは - subtech
これだと、値がArrayとかだったらうまくいかない。また繰り返しごとにevalするのは効率が悪い。こう書き換えたほうがいいだろう。
class ERB def result_hash(hash) b = binding eval hash.collect {|k,v| "#{k} = hash[#{k.inspect}];" }.join result b end end ERB.new('<%= var.inspect %>').result_hash(:var=>[1,2,3]) #=> [1, 2, 3]
ちなみにErubis::Eruby#result()はBindingもHashも受け付けるようになっている。
input = <<END <h1><%= title %></h1> <% for item in items %> <b><%= item %></b> <% end %> END require 'erubis' title = 'Example' items = [10, 20, 30] eruby = Erubis::Eruby.new(input) print eruby.result(binding) # Binding print eruby.result(:title=>title, :items=>items) # Hash
ただし、Ruby1.9からはeval中で定義されたローカル変数はeval中でのみ有効であり、evalを抜けると使えなくなるという仕様に変更されたため、これらの方法は使えない同じBindingを使えばいいだけでした(詳細はコメントをどうぞ)。こんな仕様変更するんなら、Bindingに値を設定できるようにするか、PHPのextract()関数のようにローカル変数を設定できるメソッドを追加してくれよと思うけど、今は Erubis::Eruby#evaluate() を使って我慢することにする。
Erubis::Eruby#evaluate() については次のエントリで。