Ruby CGI Adjuster
(2004.03.27新規作成。2004.12.31更新。)
概要
Rubyは、バージョン1.6から1.8にバージョンアップしたときに、CGIライブラリが変更され、非互換な部分が生じています。Ruby 1.6用に書かれたCGIスクリプトを両方で動かすことができません。
この話は、拙著『基礎から学ぶWebデータベースプログラミング』でも解説しています(p.192-193)。
Ruby CGI Adjusterは、次のことを行うための、小さなスクリプトです。
- Ruby 1.6用に書かれたCGIスクリプトを、Ruby 1.8で動くようにする。
- とち狂ったCGI#[]の挙動を修正する。
- いくつか最小限のメソッドの追加
ライセンス
Ruby's ライセンスとします。LICENSE
使い方
Ruby 1.6用のCGIスクリプトで、次のようになっているところ;
require "cgi"または
require "cgi/session"を、次のように修正します。
$COMPAT_VERSION = "1.6" require "cgisup.rb"
Ruby 1.8用のスクリプトでは、$COMPAT_VERSION に代入せずに、次のようにしてください。
require "cgisup.rb"
変更・追加するメソッド
クラスCGI
- [key]
- コントロール値またはIOを得る。
Ruby 1.6モード($COMPAT_VERSION == "1.6")では、@params[key] と同じ。
Ruby 1.8モードでは、次のように動作する。
- マルチパートではないときは、名前がkeyである最初のコントロールのコントロール値(文字列)を返す。keyコントロールがないときは、""を返す。
- マルチパートのときは、IO、StringIOまたはTempfileオブジェクトを返す。
- file_control(key)
- keyコントロール(ファイルコントロール)のコントロール値を格納するIOオブジェクトを返す。keyコントロールがないときは、nilを返す。
- マルチパートではないときは、例外RuntimeErrorを投げる。
- get(key, default = "")
- ファイルコントロール以外の値を取り出すのに使う。keyコントロールの最初のコントロール値(文字列)またはdefaultで指定される値を返す。マルチパートであるかどうかによらない。いずれでも、値を取得できる。
次のようにして使う。
require "cgisup.rb" cgi = CGI.new text = cgi.get("text") file = cgi.file_control("file") size = file.size body = file.read
クラスCGI::Session
- CGI::Session.exist?(request, option)
- セッションが存在するかどうかを調べる。requestにはCGIオブジェクトを、optionにはCGI::Sessionオブジェクトを生成するときに与えるハッシュを与える。
- CGI::Session.get(request, option)
- セッションが存在する場合のみ、Sessionオブジェクトを得る。
- CGI::Session.sweep(option)
- セッション情報を保存するファイルを削除する。option["holdtime"](整数で、単位は秒)だけ経過したセッション情報を削除する。
- update_access_time()
- セッション情報の最終アクセス時刻を更新する。CGI::Session.sweep()で参照される。
関数
- menu_control(name, options, default = nil)
- メニューコントロールHTMLを生成する。
ダウンロード
- 日付
- 2005.01.08
- 内容
-
- datesup.rbが必要だったのを修正した。datesup.rbは私の手許で使っているファイル。
- ファイル
- cgisup-20050108.rb
- 日付
- 2004.12.31
- 内容
-
- Ruby 1.8.2-releaseに対応した。
- ファイル
- cgisup-20041231.rb
- 日付
- 2004.03.27
- 内容
-
- 初公開。
- ファイル
- cgisup-20040327.rb
内部の挙動について
通常、CGIクラスの[]メソッドでフォームのコントロール値を取り出します。CGI#[]の戻り値は、Rubyのバージョン、formタグのenctype属性値によって、それぞれ次のようになります。
| enctype属性値 | Ruby 1.6の場合 | Ruby 1.8の場合 |
|---|---|---|
| application/x-www-form-urlencoded (省略値) | コントロール値(文字列)の配列、またはnil | コントロール値を格納したCGI::QueryExtension::Valueインスタンス、または"" |
| multipart/form-data | コントロール値を読むためのTempfileインスタンスの配列、またはnil | コントロール値を読むためのStringIOまたはTempfileインスタンス |
問題は、次の2点。
- Ruby 1.6用のスクリプトがRuby 1.8で動作しない。
- Ruby 1.6と1.8の両方で動くスクリプトが書けない。
どうしてこういう惚(とぼ)けた失敗をやらかすのか理解できません。ライブラリでは通常、既存のプログラムが動かなくなるような事態を避けるために、すでにあるメソッドの動作は変えず、新しいメソッドを作るものです。基礎的なものであるほど変更は慎重に行わなければなりません。
それはともかく、この問題を解決するために、次の方針で臨むことにします。
- 既存のスクリプト用に互換メソッドを用意する。
- バージョンに依存しない動作のメソッドを新たに用意する。
Rubyはすでにあるクラスの定義を書き換えられるのが助かります。Ruby 1.6用のスクリプトの場合は、1.6と同じ動作になるようにCGI#[]を定義しなおします。Ruby 1.8.1でもRuby 1.8.0と非互換な変更が入っている(ふざけているの?)ので、それも潰しておきます。