連載
» 2001年05月07日 00時00分 公開

快速MySQLでデータベースアプリ!(7):Rubyで作るデータベースCGI (2/3)

[鶴長鎮一, 渡辺恭弘,MySQLユーザ会]

簡単なサンプルとRubyスクリプトのテスト

 まずは、簡単なテーブルを作成してみましょう。この程度の操作なら直接SQL文を用意してもいいのですが、せっかくですからRubyを使用してみましょう。適当なエディタでリスト1のようなファイルを作成します。この連載を最初からお読みいただいている方は、EUCでMySQLサーバを運用していると思いますので、ソースの漢字コードもEUCに合わせてください。

 上のサンプルは大きく分けて3つのセクションで構成されています。

  • 1〜9行目 TEST_RUBYデータベースに接続してMysqlクラスのインスタンスを作成
  • 10〜16行目 クエリーの発行。見てのとおり、引数にSQL文があるだけ
  • 18〜31行目 おまけで、サーバ情報や項目情報を画面に表示させる

 最初のセクションを見ていきましょう。ユーザー名/パスワードは、MySQLサーバにデータベースを作成できる権限を持ったユーザー名に置き換えてください。

require 'mysql'
3行目 拡張ライブラリを読み込みます(requireはCのincludeと同じです。Perlではおなじみですね)
object = Mysql::new('localhost','ユーザー名','パスワード')
5行目 MySQLサーバに接続してMysqlクラスのインスタンスを作成します
object.create_db("TEST_RUBY")
6行目 TEST_RUBYデータベースを作成します(create_dbはMysqlクラスのクラスメソッドです)
object.close
7行目 データベースとの接続を切ります
object = Mysql::new('localhost','ユーザー名','パスワード','TEST_RUBY')
9行目 6行目で作成したTEST_RUBYデータベースに接続します

 Rubyでは

インスタンス.クラスメソッド

の形でメソッド呼び出しができます。もちろんメソッドによっては括弧“()”の中に引数を入れることもできます。戻り値にインスタンスを返すメソッドも中にはあるので、

インスタンス.クラスメソッド.別のクラスメソッド.さらに別のクラスメソッド

という表記で、ある機能や値を呼び出そうとします(リスト1 23行目などがそうです)。少々ややこしいですが、目的の値なり文字列が得られるまでメソッドを継ぎ足していけばよいわけです。

 例えば、Perlで最後の1文字を削除するchop()という関数は以下のように使います

text = "hogehoge";
chop(text);

 Rubyの場合は、

text = "hogehoge";
text.chop!;

 これで“hogehog”になりました。ちなみに、chopはStringクラスのクラスメソッドです(Rubyでは、ただのテキストも数値もオブジェクトとして扱われます。この場合“hogehoge”はStringクラスのインスタンスです)。

 2番目のセクションは、

object.query('create table test_table (name char(32),price int)')
10行目 クエリーを発行してテーブルを作成します
object.query("insert into test_table values ('りんご',300);")
object.query("insert into test_table values ('みかん',80);")
object.query("insert into test_table values ('梨',150);")
object.query("insert into test_table values ('桃',250);")
object.query("insert into test_table values ('メロン',3450);")
object.query("insert into test_table values ('いちご',450);")
11〜16行目 クエリー文を発行してフィールドを挿入します

 18行目から31行目までの第3セクションは、前述のとおりデータベースに関する情報の取得と表示です。

 では実行してみましょう。

$ ruby sample1.rb
ATMARKIT,TEST_RUBY,mysql,test  [1]
3.23.28-gamma-log              [2]
Localhost via UNIX socket      [3]
2                              [4]
name                           [5]
price                          [6]
test_table                     [7]
254                            [8]
32                             [9]

1.データベースの一覧(今回作成したTEST_RUBY以外にもデータベースは存在しています)
2.MySQLのバージョン情報
3.ホスト情報(Rubyが動作するサーバとMySQLが動作するサーバが同一なのでこのような表示)
4.テーブルの項目数(nameとpriceだけ)
5.項目名
6.項目名
7.テーブル名
8.項目の型。0から254までを表現できる(char型)
9.項目の長さchar(32)の32

 以上の作業で下のテーブルができあがりました。確認しておきましょう。

# mysqlshow TEST_RUBY test_table %
Database: TEST_RUBY Table: test_table Rows: 6 Wildcard: %
+-------+----------+------+-----+---------+-------+----------------------+
| Field | Type     | Null | Key | Default | Extra | Privileges           |
+-------+----------+------+-----+---------+-------+----------------------+
| name  | char(32) | YES  |     |         |       | select,insert,update |
| price | int(11)  | YES  |     |         |       | select,insert,update |
+-------+----------+------+-----+---------+-------+----------------------+ 
 
# mysql TEST_RUBY
mysql> SELECT * FROM test_table;
+--------+-------+
| name   | price |
+--------+-------+
| りんご |   300 |
| みかん |    80 |
| 梨     |   150 |
| 桃     |   250 |
| メロン |  3450 |
| いちご |   450 |
+--------+-------+
6 rows in set (0.00 sec) 

 少々テーブルがさみしいなと思ったら、適当にクエリー文を追加したり5、6、7、10行目を削除してスクリプトを再度実行してみてください。

 いつまでもスーパーユーザーでの作業は危険です。ここでMySQLサーバに適切な参照権を設定します。

# mysql
mysql> GRANT Select,Update,Insert,Delete ON TEST_RUBY.* TO 'test' IDENTIFIED BY 'test2001';
Query OK, 0 rows affected (0.00 sec)

Webアプリケーションの作成

 それでは、作成したテーブルをWebで検索するCGIを作成してみましょう。

CGI呼び出し用Webフォーム

 まずはCGIを呼び出すためのHTMLファイルを作成します。リスト2のような感じでよいでしょう。名前と値段(一致・以上・以下)で検索します。EUCで保存することをお忘れなく。

Rubyで作るCGI

 次にCGIプログラムの本体(リスト3)を書きます。処理の流れは以下のようになります。

  • フォームデータの受け取り(7〜12行目)
  • フォームデータを加工して、クエリー文を発行(14〜25行目)
  • 結果を加工(27〜47行目)
  • HTMLを作成・出力(49〜56行目)

 では細かく見ていくことにしましょう。

require "cgi"

 まず4行目でCGIの作成に便利なライブラリを読み込みます。このライブラリを使うことで、7行目から12行目の要領で、HTMLフォーム中の値を取り込むことができます。

case f_zyoken
when 1
        zyoken = "="
when 2
        zyoken = ">="
when 3
        zyoken = "<="
end

 14行目から21行目までは、セレクトフォーム“一致”、“以上”、“以下”の値をSQL文で使用できるように、それぞれ“=”、“>=”、“<=”に変換しています。

msql = Mysql::new('192.168.1.10','test','test2001','TEST_RUBY')
res_price = msql.query("select name,price from test_table where price #{zyoken} '#{Mysql::quote f_price}'")
res_name = msql.query("select name,price from test_table where name='#{Mysql::quote f_name}'")

 23行目から25行目まではクエリーの発行です。注目していただきたいのは、

'#{Mysql::quote f_price}'

です。これはMysqlクラスのクォート機能です。フォームにはユーザーがどんな文字列を入力するか分かりません。そのため、特殊文字などをエスケープするためMysql::quoteを使用し、さらに一番強力な“'”でエスケープしておきます。

if res_price.num_rows == 0 && res_name.num_rows == 0
        serched_out = "見つかりませんでした"
else
        gokei = res_price.num_rows + res_name.num_rows
        serched_out = "#{gokei}件見つかりました"
end

 27行目から32行目までは検索結果数の格納です。Mysqlresクラスのnum_rowsメソッドで検索件数を得ることができます。

res_name.each do |name,price|
        name_array[i] = "#{name}"
        price_array[i] ="#{price}"
        i += 1
end
res_price.each do |name,price|
        name_array[i] = "#{name}"
        price_array[i] ="#{price}"
        i += 1
end

 38行目から47行目まではMysqlresクラスからフィールドの値を配列に格納させています。

puts '<html><head><title>Ruby&MySQL</title> </head><body bgcolor="#CCFFCC"><center>'
puts serched_out
puts '<table cellspacing="0" cellpadding="2" width=280 bgcolor="#CCFFCC" border="1">'
for count in 0..i-1
        puts '<tr><th bgcolor="#FFCCCC" width=50%>' + name_array[count]
        puts '<td bgcolor="white">' + price_array[count] + "円"
end
puts '</table></body></html>'

 49行目から56行目までで、配列に格納されたフィールドの値をテーブルに変換して、HTMLとして出力します。

将来も期待できるRuby

 Rubyには、PHPのようにHTMLに埋め込むことができるeRubyerbの2種類の埋め込みRubyと、PerlのようにApacheのモジュールとして高速に動作するmod_rubyなどがあります。オブジェクト指向という言葉にとらわれず、サンプルのようなスクリプトから始めましょう。RubyはPerlやPHPのように気楽に使用できる言語であり、非常に記述が少なくて済み、本来の処理以外に気を使う必要もありません(インデントや;を強要したりはしません)。

 日本発の先進的言語として、いまRubyは世界から注目されはじめています。Perlではほとんど不可能なグループによる本格的な開発や保守もRubyなら十分可能ではないかと期待されています。Rubyの今後に期待しましょう。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。