Ruby で CGI スクリプト

Ruby は、インタプリタ型の言語である。 正規表現にも強い。オブジェクト指向なので、 プログラムの行数を少なくすることができる。

Ruby では、CGI スクリプトを簡単に作ることができる。 今までのスクリプトに使われている言語は、開発者が日本人でないために、 日本語環境に問題が発生することが多かった。 上記の強みにも加え日本語との相性の良さで、 CGI スクリプトを作成するのに都合がよい言語として認識されている。

CGI入門

HTML文書内にあるデータ入力ウィンドウにユーザがデータを入力すると、 それに応じて変化するものを CGI (Common Gateway Interface) という。 入力された値を確定することにより、 他のプログラムに受け渡しすようなしくみをスクリプト (script) と呼ぶ。 CGI スクリプトを Ruby 言語を使って書くことができる。

CGI スクリプトの例

例えば、アンケート用紙などを作る際には CGI スクリプトを使用している。

作ってみたくなっただろうか? まずは実際に入力して確かめよう。

CGI 専用作業 directory

CGI は、専用の作業 directory を必要とする。 それを、rubycgi としよう。ホームページで使用するので、 public_html の下にこの directory を作る必要がある。

% cd public_html
% mkdir rubycgi
% chmod 1777 rubycgi

ここに、入力を受ける HTML 文書と、結果を吐き出すプログラムを仕込む。

CGIの作り方

CGIは、いくつかの分担プログラムとその連係動作からなる。

CGI を使用することを宣言しよう

全ての .rb ファイルを CGI だとするのは他の作業に支障が出る。 そこで、この rubycgi の下の .rb ファイルのみが CGI スクリプトであると設定する。

rubycgi の下に、 .htaccessという名前のファイルを作成する。

˜/public_html/rubycgi/.htaccess ファイルを新規に開き、 以下の内容を記述して保存する。



AddHandler cgi-script   .rb
Options    +ExecCGI

以後、このディレクトリに作成する .rb という名前で 終わるファイルはCGIスクリプトと認識される。

利用者にデータを入力させる部品

利用者にデータを入力させるには、 form と呼ばれる tag で作る。


<form method="POST" action="./結果を吐かせるプログラム.rb">
  入力させるしくみ

</form>

としている。この中を、入力フォームの部品で埋める。

入力 form の部品にはいくつか種類があるので、みてみよう。

入力 form の部品

CGI 専用 directory の中で行うこと

全てができあがると、

% ls -la
.htaccess    入力を促すホームページ.html   結果を吐かせるプログラム.rb

となっている。到着駅を選ぶプログラムを作ろう。 ˜/public_html/rubycgi の下に、 入力を促す HTML 文書 cgi_ticket.html と、 結果を吐かせるプログラム cgi_ticket.rb をおくことにする。

基本の CGI ホームページの作りかた

HTML の基本

入力を促す CGI ホームページの作りかた

それでは、cgi_ticket.html を作ってみよう。


<html>
<head>
   <title>
   オンライン券売機
   </title>
</head>
<body>
<form method="POST" action="./cgi_ticket.rb">
<ul>
<li>出発駅: 酒田</li>
<li>到着駅: 
     <select name="arrival">
			    <option> 東酒田
			    <option> 砂越
			    <option> 北余目
			    <option> 余目
			    <option> 北余目
			    <option> 西袋
			    <option> 藤島
			    <option> 鶴岡
     </select> 
</li>
</ul>
<p>
<input type="submit" value="OK">
<input type="reset" value="clear">
</p>
</form>
</body>
</html>

自分のホームの下の ˜/public_html/rubycgi の cgi_ticket.html を開けてみる。

select tag の例

と見えたなら、できあがり。動作の解説 に進もう。

CGI スクリプトの解説

form tag の中身を見ていこう。

ドロップダウンメニュー

  • <select> </select> tag は、 ドロップダウンメニューを作る tag である。
  • name は CGI 変数で、名称を担う (ホームページ内に複数あるとき、どのドロップダウンメニューか区別するため)。
  • option で、メニューを選ぶことができる。

送信ボタン

input tag の中では、次のようなルールがある。

type で、入力 form の部品を指定する。 value は CGI 変数の値である。 送信ボタンが押されると、value の値を Ruby に送り込む。

  • type が submit : 送信させる
  • type が reset : リセットさせる

プログラムはこちら。 Ctrl-u でソースを見ることができる。

動作プログラム作成

次に、ユーザが選んだ反応の結果、 行われる動作プログラムを作る。 ここでは HTML 文書を吐きだすプログラムを作る。

結果を得るためのしくみ

CGI スクリプトで、結果が選ぶことができるようになった。 その結果を HTML 文書として書き込むプログラムを作る。 HTML 文書を吐き出す部分を、Ruby が担う。 今の例では cgi_ticket.rb である。

構造は次のとおり。

ruby を動かす宣言 #!/usr/bin/env ruby
プログラムを EUC-JP で #coding: euc-jp
CGI を使う宣言 require 'cgi'
EUC-JP で受け取り CGI 変数= CGI.new(:accept_charset => "EUC-JP")
EUC-JP で書き出し print("Content-type: text/html; charset=EUC-JP\n\n")
作った CGI スクリプトの名前の定義Hash を用いる
実行して吐きだす HTML 文書のドラフト print 文で HTML 文書を出力

Ruby で CGI を作る宣言


#!/usr/bin/env ruby
#coding: euc-jp

require 'cgi'                 # CGI を使う
cgi = CGI.new(:accept_charset => "EUC-JP")        # CGI は EUC-JP で受け付ける
print("Content-type: text/html; charset=EUC-JP\n\n")  # CGI の値を EUC-JP で書き出す

ruby を使うのに、env コマンドを立ち上げて使う。 #!/usr/koeki/bin/ruby のかわり。今回はこちらを使う。

cgi = CGI.new で、CGI 用の Hash が完成した。 cgi に、name として、CGI 変数 "arrival" が代入されている。 cgi の value は、option で選ばれた "余目" などの駅名が代入されている。 CGI 変数 "arrival" には "余目" など洗濯された値が入っている。

CGI の動作の定義


arv = cgi["arrival"]
select tag のとき、
Hash での key は CGI スクリプトにおいて name である。
Hash での value は CGI スクリプトにおいて option である。

Ruby の変数 arv とすると、bt には cgi["arrival"] の option が代入されている。

printf("<p>%s駅</p>",arv)

などが HTML 文書で実現できれば完成である。 HTML 文書部分はこちら

日本語の受け渡し

特殊な文字を使う国、たとえば日本語などでは、プログラムにおいて、 EUC-JP で表示することを明示する。

#coding: euc-jp

Ruby CGI では、さらに、CGI で受け渡された値をもらって、 プログラムに変換するため、

CGI.new(:accept_charset => "EUC-JP")

で確実に EUC-JP で値を持ち出し、HTML で出力するため、HTML でも

Content-type: text/html; charset=EUC-JP

が必要となる。CGI のように、 動的に出力するようなプログラムで日本語コードを扱う場合には、 どの部分で使用しているのか理解しながらプログラミングするとよい。

print() 文と HTML 文書のなかみ

CGI スクリプトを書かせる部分を設定したら、 残りの部分が HTML 文書を吐きださせる部分である。


print("<html>\n")
print("<head>\n")
print("<title>オンライン券売機</title>\n")
print("</head>\n")
print("<body>\n")

printf("<h1>到着駅は %s ですね</h1>\n", arv)

print("</body>\n")
print("</html>\n")

Ruby の print() 文

HTML と Ruby の改行文字の出力が独立であることに慣れるために、 少し練習しておこう。.rb で、print 文の中に改行を入れると、 文字が表示されることを思い出そう。


%irb
irb(main):001:0> print("<html>\n<body>\n改行のちがい\n</body>\n</html>\n")

<html>
<body>
改行のちがい
</body>
</html>
=> nil

.rb を動かした結果、 print() 文の中に \n を挟むと、改行して表示された。 ここでの構造は

print("HTML 文書の命令\n")

#{変数} は指定子 (%d, %f, %s) である。.rb で試してみよう。

% irb                             

irb(main):001:0> sumomo = "すもも"
=> "すもも"
irb(main):002:0> printf("今表示するのは#{sumomo}\n")
今表示するのはすもも
=> nil

もちろん計算もできる。


irb(main):004:0> printf("今表示するのは#{11+29}\n")
今表示するのは40
nil

自動券売機

以上を合わせて、cgi_ticket.rb は、次のようになる。 cgi_ticket.rb

Ruby のプログラムなので、 chmod +x ˜/public_html/rubycgi/cgi_ticket.rb を忘れずに!

firefox で吐きだしたソースを読むには

実際にホームページで見えている HTML ファイルは、このようなものである。 Ctrl u で、ソースを見てみよう。


<html>
<head>
<title>オンライン券売機</title>
</head>
<body>
<h1>到着駅: 余目駅</h1>
</body>
</html>

試作品のエラーを探せ

うまくいかないときには、 まずプログラムの属性を調べる。

-rwxr-xrwx 1 ta05001 users 4321 Nov 26 2006 動くプログラム.rb

となっていなければ、chmod 忘れである。 文法自体がどこかで間違っている場合もある。 次のようにすると調べることができる。


pan{c11xyyy}% ssh roy
c11xyyy's password: roy で Emacs を使うときのパスワード
roy{c11xyyy}% ˜/public_html/rubycgi
roy{c11xyyy}% ./cgi_ticket.rb

実際に使用している directory まで行って起動させる。


(offline mode: enter name=value pairs on standard input)

とデバッグモードになるので、cgi["CGI 変数"]と書いた CGI 変数の部分に、 具体名を書いて実行する。ここでは arrival を選ばせていたので、

arrival="東京"

と指定してみる。全ての CGI 変数を入力したら Ctrl d とする。 プログラムやHTML 文書に誤りがなければ


Content-type: text/html; charset=EUC-JP

<html>
<head>

<title>オンライン券売機</title>
</head>
<body>
<h1>到着駅: 東京</h1>
</body>
</html>

と出力されるはずである。 これがうまくいったら、実際に実行しても動くプログラムになっているはずである。

次回以降

次回以降は集計結果を表示するプログラムを作れるように準備していく。 今回のアンケート結果は こちら

HTML ソース

ここではソースを公開する。ダウンロードするソースは ここ


<html>
<body>
<form method="POST" action="./love.rb">
<p>名前: <input name="nickname" type="text" maxlength="40"></p>
<p>情報の講義は好きですか?<select name="love">
			    <option checked> あいしてます
			    <option> まあすき
			    <option> そんなでも
			   </select></p>
<br>
<p>例として紹介されたプログラムはどのように感じましたか?(ひとつだけ)</p>
<p>
<input type="radio" name="level" value="やさしい"> やさしい<br>
<input type="radio" name="level" value="ふつう" checked> ふつう<br>
<input type="radio" name="level" value="ややこしい"> ややこしい
</p>
<br>
<p>情報の講義のイメージはどれに当てはまりますか?(いくつでも)</p>
<p>
<input type="checkbox" name="interst" value="おもしろい"> おもしろい
<input type="checkbox" name="worth" value="やりがいある"> やりがいがある
<input type="checkbox" name="notime" value="時間がない"> 時間がない
<input type="checkbox" name="future" value="将来のための" checked> 将来のため
<input type="checkbox" name="tedious" value="めんどうな"> めんどうだ
</p>
<br>
<p>
後輩へのメッセージ (200 文字以内): </p>
<p><textarea name="reason" rows="5" cols="40">
あなたのひとことが勇気を与えます</textarea></p>


<input type="submit" value="OK">
<input type="reset" value="clear"><br>
</p>
</form>
</html>
</body>

あらかじめ初期値を作っておくときには input 内に checked を用いる。 その他はきまりであると思ってよい。大きさの変更は数値を見て適宜決めればよい。

HTML のファイルの書き出し

ファイルの書き出し を参考にする。