ERBの使い方

下記のページを参考にERBの使い方を勉強する。
Rubyist Magazine - 標準添付ライブラリ紹介 【第 10 回】 ERB

eRuby


eRubyでは任意のテキストファイルにRubyスクリプトを埋め込める。基本的には次のマークアップ(eRubyタグ)を使ってRubyスクリプトを埋め込む。

<%...%> Rubyスクリプト片をその場で実行
<%=...%> 式を評価した結果をその場に挿入
<%#...%> eRubyのコメント

eRubyはHTMLやXMLに限らず、任意のテキストファイルの出力に使用できる。

ERBの基本的な使い方


ERBの一番基本的な使い方は、eRubyスクリプトをERB.newの第一引数に指定してERBオブジェクトを生成し、resultメソッドで結果を文字列で取得する。

require 'erb'
str = "hoge"
erb = ERB.new("value = <%= str %>")
puts erb.result(binding)

f:id:ayaketan:20111218151112j:image

次にかけ算の九九の表を生成するスクリプトを作ってみる。

require 'erb'
puts ERB.new(DATA.read).result(binding)
__END__
 <% (1..9).each do |y| %>  <%= y %><% end %>
<%
(1..9).each do |x|
%><%= x %><%
  (1..9).each do |y|
%><%= sprintf '%3d', x*y %><%
  end
%>
<% end %>

f:id:ayaketan:20111218151113j:image
まず1行目でERBを使うためにerbライブラリをrequireしている。
次にDATA.readで__END__以降の内容を読み込んでいる。ここでは例を簡単にするためにRubyスクリプトの末尾に__END__を使ってeRubyスクリプトを読み込んでいるが、普通は別ファイルから読み込む。
そして読み込んだeRubyスクリプトを使ってERBオブジェクトを生成して、resultメソッドを使って結果の文字列を取得している。resultメソッドの引数に組み込み関数bindingを使って取得したBindingオブジェクトを指定している。
最後に結果の文字列をputsを使って出力している。

ERB#run


ERB#runはERB#resultの結果をそのまま標準出力に出力する。結果の文字列を加工したり他の処理に利用したりする場合はERB#resultを使う必要があるが、出力するだけならERB#runが使える。
先ほどの九九のプログラムをERB#runに書き換える。

require 'erb'
ERB.new(DATA.read).run(binding)
__END__
 <% (1..9).each do |y| %>  <%= y %><% end %>
<%
(1..9).each do |x|
%><%= x %><%
  (1..9).each do |y|
%><%= sprintf '%3d', x*y %><%
  end
%>
<% end %>

f:id:ayaketan:20111218151114j:image

ERB#src


ERB#srcはeRubyをRubyスクリプトに変換したソースを返す。Rubyスクリプトに変換した結果をキャッシュしたり、evalで実行したりすることができる。
stftimeという存在しない関数を使った場合のエラーを比較する。
まずはevalを使わない場合

require 'erb'
now = Time.now
ERB.new(DATA.read).run(binding)
__END__
今日は<%= now.stftime("%Y-%m-%d") %>です。

f:id:ayaketan:20111218151115j:image

次にevalを使った場合

require 'erb'
now = Time.now
puts eval(ERB.new(DATA.read).src, binding, __FILE__, __LINE__+1)
__END__
今日は<%= now.stftime("%Y-%m-%d") %>です。

f:id:ayaketan:20111218151116j:image
evalを使うと、「test.rb:5:in...」といったようにファイル名を行番号を表示することができる。
このevalを使うために、Rubyスクリプトに変換したソースを返すERB.srcを使っている。

ERB#filename,ERB#filename=


ERB#filename,ERB#filename=を使って、エラーメッセージ用のファイル名の取得や設定ができる。

require 'erb'
fname = "erb.txt"
erb = ERB.new(File.read(fname))
puts erb.filename     # ファイル名は取得できていないので空
erb.filename = fname  # ファイル名を設定
puts erb.filename     # 設定したファイル名を表示
puts erb.result(binding) #ERBファイルの中身を表示

f:id:ayaketan:20111218151117j:image

trim_mode


先ほど勉強した九九の例などでは余分な改行や空白が入らないようにするために「<%」や「%>」などの位置がわかりにくくなっている。
HTMLの場合は改行の位置や空白などは気にせずに書いても、ブラウザで表示させたときに連続する空白は単独の空白と同じ扱いになるので気にならないが、HTMLを直接見た場合には気になってしまう。
そこでERBにはtrim_modeという機能が付いている。

trim_mode='-'


'-'というtrim_modeでは以下の違いがある。

<%- (「<%-」のインデントに使われている)行頭の空白文字を削除
-%> 直後の改行を出力しない

「<%-」と行頭の間に空白以外の文字があったり、「-%>」と改行の間に(空白も含めて)他のもじがあったりすると、「<%」や「%>」と同じ挙動になる。

trim_modeの使用例


先ほどの九九の例を'-'というtrim_modeを使って書き直してみる。

require 'erb'
puts ERB.new(DATA.read, nil, '-').result(binding)
__END__
 <% (1..9).each do |y| %>  <%= y %><% end %>
<%- (1..9).each do |x| -%>
<%= x -%>
  <%- (1..9).each do |y| -%>
<%= sprintf '%3d', x*y -%>
  <%- end %>
<%- end -%>

f:id:ayaketan:20111218151118j:image
「<%」(または「「<%=」) と「%>」の対応がそれぞれの行に収まっていたり、 内側のループがインデントできたりして、最初の例より読みやすくできている。

trim_mode='%'


trim_modeに'%'を指定すると「%」で始まる行を「<%...%>」と同じようにRubyスクリプトとして実行する。その行の改行は出力しない。

require 'erb'
puts ERB.new(DATA.read, nil, '%').result(binding)
__END__
% require 'mathn'
<%= 1/2 + 1/3 %>

f:id:ayaketan:20111218151119j:image

その他のtrim_mode


'-'と'%'の他に改行の扱いを変える'>'と'<>'がある

> 行末が「%>」のときに改行を出力しない
<> 行頭が「<%」で行末が「%>」のときに改行を出力しない