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 以外の場合