Rubyで作るデータベースCGI:快速MySQLでデータベースアプリ!(7)(2/3 ページ)
日本発のオブジェクト指向スクリプト言語RubyとMySQLは非常に相性がいい。今回はこのRubyを使ってデータベースアプリを作ってみよう。
簡単なサンプルとRubyスクリプトのテスト
まずは、簡単なテーブルを作成してみましょう。この程度の操作なら直接SQL文を用意してもいいのですが、せっかくですからRubyを使用してみましょう。適当なエディタでリスト1のようなファイルを作成します。この連載を最初からお読みいただいている方は、EUCでMySQLサーバを運用していると思いますので、ソースの漢字コードもEUCに合わせてください。
上のサンプルは大きく分けて3つのセクションで構成されています。
- 1〜9行目 TEST_RUBYデータベースに接続してMysqlクラスのインスタンスを作成
- 10〜16行目 クエリーの発行。見てのとおり、引数にSQL文があるだけ
- 18〜31行目 おまけで、サーバ情報や項目情報を画面に表示させる
最初のセクションを見ていきましょう。ユーザー名/パスワードは、MySQLサーバにデータベースを作成できる権限を持ったユーザー名に置き換えてください。
require 'mysql'
object = Mysql::new('localhost','ユーザー名','パスワード')
object.create_db("TEST_RUBY")
object.close
object = Mysql::new('localhost','ユーザー名','パスワード','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)')
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);")
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に埋め込むことができるeRubyとerbの2種類の埋め込みRubyと、PerlのようにApacheのモジュールとして高速に動作するmod_rubyなどがあります。オブジェクト指向という言葉にとらわれず、サンプルのようなスクリプトから始めましょう。RubyはPerlやPHPのように気楽に使用できる言語であり、非常に記述が少なくて済み、本来の処理以外に気を使う必要もありません(インデントや;を強要したりはしません)。
日本発の先進的言語として、いまRubyは世界から注目されはじめています。Perlではほとんど不可能なグループによる本格的な開発や保守もRubyなら十分可能ではないかと期待されています。Rubyの今後に期待しましょう。
Copyright © ITmedia, Inc. All Rights Reserved.