eRuby のファイルから Ruby の文と式だけを抜き出す
eRuby ファイルに Syntax error があると、該当箇所を見つけるのはかなり困難である。理由は簡単で、HTML と Ruby コードとが混じっているから。
たとえば <% for item in list %> と <% end %> のあいだにたくさんの HTML タグが入っていると、それだけで for と end の対応を確認するのが難しくなる。
たとえばこんな hoge.rhtml があったとする。
<html>
<body>
<h1><%=h @title %></h1>
<% if !@list || @list.empty? %>
<p>not found.</p>
<% else %>
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Site</th>
</tr>
</thead>
<tbody>
<% i = 0 %>
<% for item in @list %>
<% i += 1 %>
<% color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF' %>
<tr bgcolor="<%= color %>">
<td><%= i %></td>
<td><%=h item.name %></td>
<% if item.url %>
<td><a href="<%= item.url %>"><%=h item.url %></a></td>
<% else %>
<td>-</td>
<% end %>
</tr>
</tbody>
</table>
<% end %>
</body>
</html>
この hoge.rhtml には Syntax error がある。それは次のようにして確かめることができる。
$ erb -x hoge.rhtml | ruby -wc -:34: syntax error, unexpected $end, expecting kEND
しかし、実際にどこが原因で Syntax error になっているのかは分からない。hoge.rhtml をみても、HTML と Ruby コードが入り交じっていて、見つけるのが困難である。
こんなときは、Erubis に -x -E NoText をつけると、HTML を取り去って Ruby コードだけを抜き出してくれる (逆に HTML だけを抜き出したいときは -x -E NoCode を指定する)。
$ erubis -x -E NoText hoge.rhtml
_buf = '';
_buf << (h @title ).to_s;
if !@list || @list.empty?
else
i = 0
for item in @list
i += 1
color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'
_buf << ( color ).to_s;
_buf << ( i ).to_s;
_buf << (h item.name ).to_s;
if item.url
_buf << ( item.url ).to_s; _buf << (h item.url ).to_s;
else
end
end
_buf.to_s
この機能は非常に便利なので、-x -E NoText のかわりに -X というショートカットが用意されている。
また -U をつけると連続する空行を圧縮し (uniq)、-C をつけると空行を取り除き (compact)、-N をつけると行番号が表示される (number)。
$ erubis -XNC hoge.rhtml
1: _buf = '';
3: _buf << ( @title ).to_s;
4: if !@list || @list.empty?
6: else
16: i = 0
17: for item in @list
18: i += 1
19: color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'
20: _buf << ( color ).to_s;
21: _buf << (h i ).to_s;
22: _buf << (h item.name ).to_s;
23: if item.url
24: _buf << ( item.url ).to_s; _buf << (h item.url ).to_s;
25: else
27: end
31: end
34: _buf.to_s
これを見れば一目瞭然。17 行目の for 文に対応する end が抜けていることがわかる。
このように、Erubis の -E NoText を使うと Ruby のコードだけを抜き出してくれるので、チェックが簡単になる。
また Erubis は PHP にも対応していて、PHP ファイルから PHP のコードのみを抜き出すことができる (なんというムダ機能!)。
$ erubis -l php --pi=php -XNC --trim=false hoge.php
3: <?php echo $title; ?>
4: <?php if (! $list) { ?>
6: <?php } else { ?>
16: <?php $i = 0; ?>
17: <?php foreach ($list as $item) { ?>
18: <?php $i += 1; ?>
19: <?php $color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'; ?>
20: <?php echo $color; ?>
21: <?php echo $i; ?>
22: <?php echo $item->name; ?>
23: <?php if ($item->url) { ?>
24: <?php echo $item->url; ?> <?php $item->url; ?>
25: <?php } else { ?>
27: <?php } ?>
31: <?php } ?>
これらに限らず、Erubis は拡張性が非常に高い。Erubis は高速性が注目されているけど、それに比べると拡張性の高さはあまり知られていない。たとえば -E NoText の機能は、たったこれだけで実現されている。
module Erubis
module NoTextEnhancer
def add_text(src, text)
src << ("\n" * text.count("\n")) ## テキスト行数分の改行を追加
if text[-1] != ?\n ## テキストが改行で終わってない場合は、
count = text.length - text.rindex(?\n) - 1
src << (' ' * count) ## 最後の行の文字数分だけ半角空白を追加
end
end
end
end
class MyEruby < Erubis::Eruby
include Erubis::NoTextEnhancer
end
Erubis は他にも機能てんこもりなので、知りたい人はユーザーズガイドのChapter3. Enhancerとかをどうぞ。
なお Erubis では -z を指定すると Syntax error をチェックしてくれる。これは erb -x hoge.rhtml | ruby -wc と比べると、複数ファイルを一度にチェックできるという利点がある。
$ erubis -z views/**/*.rhtml ## zsh の場合 $ find views -name '*.rhtml' | xargs erubis -z ## zsh 以外の場合