erubyをERBに置き替える その2
前回の「erubyをERBに置き替える その1」では、Rubyに付属しているerbコマンドを使って、無理やりeRubyファイルをCGI化してみました。
一般的には、eRubyで書いたファイルとは別に、それを解釈するCGIスクリプトを用意しておいて、Apacheの設定でファイルをCGIに食わせる方法を取るようです。掌田津耶乃のさんの「ERBによるWebアプリケーション開発」という解説が分かりやすかったので、これに従って試してみました。
まず、.htaccessにAddTypeとActionディレクティブを書いて、拡張子「.rhtml」のファイルが「/ruby.cgi」で処理されるように設定します(もちろん、httpd.confの該当<Directory>に直接書いてもOKです)。
AddType application/x-httpd-eruby .rhtml
Action application/x-httpd-eruby /ruby.cgi
次に、「ruby.cgi」ファイルを作って下記の内容を記載し、実行権限を付与します。
#!/usr/local/bin/ruby
require 'erb'
require 'cgi'
puts 'Content-Type: text/html; charset=utf-8'
puts
ERB.new(IO.read(CGI.new.path_translated)).run
「fruits.rhtml」ファイルを作り、eRuby形式で中身を記載します。ひとまず、前回うまく行った「むりやり版」から、shebangと「_erbout = ““」とHTTPレスポンスヘッダを取り除いた形にしてみます。
<%
itemList = []
File.foreach("list.db") do |line|
line.chomp!
itemList.push(line)
end
%><html>
<body>
% itemList.each do |item|
<p><%=item%></p>
% end
</body>
</html>
ここで読み込んでいる「list.db」の中身は前回と同じです。
りんご
みかん
バナナ
で、早速ブラウザからこの「fruits.rhtml」にアクセスしてみると、Internal Server Errorが出てしまいました。
[Sun Feb 23 19:56:40.317826 2014] [core:alert] [pid 1576] [client 12.34.56.78:12345] /path/to/the/doc/.htaccess: Invalid command 'Action', perhaps misspelled or defined by a module not included in the server configuration
.htaccessに書いたActionディレクティブがエラーになっているようです。Apacheのマニュアルによると、Actionディレクティブを使うためには、mod_actionsをロードする必要があります。デフォルトのhttpd.confでは下記の行がコメントアウトされているので、#を取って有効化します。
LoadModule actions_module libexec/apache24/mod_actions.so
Apacheを再起動し、再びブラウザで「fruits.rhtml」にアクセスすると、Internal Server Errorは出なくなったものの、今度は真っ白なページが表示されてしまいました。Apacheのエラーログに何か出ています。
[Sun Feb 23 20:00:56.582875 2014] [cgi:error] [pid 1620] [client 12.34.56.78:12345] AH01215: (erb):10:in `<main>': undefined local variable or method `item' for main:Object (NameError)
[Sun Feb 23 20:00:56.583277 2014] [cgi:error] [pid 1620] [client 12.34.56.78:12345] AH01215: \tfrom /usr/local/lib/ruby/1.9/erb.rb:838:in `eval'
[Sun Feb 23 20:00:56.583385 2014] [cgi:error] [pid 1620] [client 12.34.56.78:12345] AH01215: \tfrom /usr/local/lib/ruby/1.9/erb.rb:838:in `result'
[Sun Feb 23 20:00:56.583434 2014] [cgi:error] [pid 1620] [client 12.34.56.78:12345] AH01215: \tfrom /usr/local/lib/ruby/1.9/erb.rb:820:in `run'
[Sun Feb 23 20:00:56.583487 2014] [cgi:error] [pid 1620] [client 12.34.56.78:12345] AH01215: \tfrom /path/to/the/doc/ruby.cgi:6:in `<main>'
fruits.rhtmlの10行目で、itemが未定義だと言ってるようです。どうやら、この方式では行頭が%の行がRubyスクリプト片として認識されていないみたいです。なので、「% xxx」の行を「<% xxx %>」に変更してみます。
<%
itemList = []
File.foreach("list.db") do |line|
line.chomp!
itemList.push(line)
end
%><html>
<body>
<% itemList.each do |item| %>
<p><%=item%></p>
<% end %>
</body>
</html>
もう一度「fruits.rhtml」にアクセスすると、今度は正常に画面が表示されました。HTMLのソースはこんな感じです。
<html>
<body>
<p>りんご</p>
<p>みかん</p>
<p>バナナ</p>
</body>
</html>
行頭%の行は出力からは完全抹殺されていたのに対して、<% %>だと末尾の改行は残るので、間に空行が入っています。それ以外は特に問題ありません。
なお、実際には前回と同様、エンコーディングをきちんと合わせておかないと、エラーや文字化けの原因になるので、その辺を考慮するとこんな感じになります(スクリプト自体にも仮名漢字を入れてみました)。
<%# coding: UTF-8 %>
<%
itemList = []
File.open("list.db", "r:utf-8") do |file|
file.each() do |line|
line.chomp!
itemList.push(line)
end
end
%><html>
<body>
<h1>果物リスト</h1>
<% itemList.each do |item| %>
<p><%=item%></p>
<% end %>
</body>
</html>
これで、複数のeRubyファイルが簡単に作れるようになりました。
※バージョンメモ
- FreeBSD 10.0-RELEASE-p0 amd64
- ruby-1.9.3.484_1,1
- apache24-2.4.6_1
※更新履歴
- 2014-04-20 最後の例から「line.encode(Encoding::UTF_8)」の行を削除。