青山です。

cgi-lib.rb や CGI.rb の話が出て来たので、HTML generator についての話を
再燃させます。

cgi-lib.rb は本来の CGI としての機能はすでに一通りもっており、足りない
機能は HTTP, HTML についてのものでした。そして、そられは HTTP, HTML の
ライブラリとして独立の方が良いだろうという事で、cgi-lib.rb の拡張はス
トップ。html-gen.rb はサンプルコードが出たものの、そのまま眠ってしまっ
たというのが現状です。

しかし、ここにきて cookie への対応が行われ、それに伴い HTTP ヘッダを扱
う機能が追加されました。次に要求されるのは当然ながら HTML の生成となり
ます。

HTTP ヘッダの扱いについても色々あるのですが、まずは最もインターフェイ
スの案が多数でる HTML の生成について取り上げてみます。(長い前置きです
が、前回の cgi-lib.rb の拡張から1年以上間があいたので)

それでは、その多数あるであろう案のいくつかをあげてみます。

print (
  HTTP.header,
  HTML.start do
    HTML.head do
      HTML.title do
        "title"
      end
    end
    HTML.body do
      HTML.p do
        "message"
      end
    end
  end
)

これは Ruby の文法にそのまま馴染ませたようなタイプです。HTML の出力先
を扱うようなインスタンス変数を用意し、print() を省略させる手もあります。
さらに、モジュールとして読み込み、つぎのようにする案もあります。

header
start do
  head do
    title do
      "title"
    end
  end
  body do
    p do
      "message"
    end
  end
end

かなりすっきりしますが、大きな欠点として、p が上書きされてしまうという
事があります。

この他、イテレータを使わずに CGI.pm 風だとこんな感じでしょう。

print (
  HTTP.header,
  HTML.start_html({"title" => "title"}),
    HTML.p("message"),
  HTML.end_html
)

そして、CGI.pm でもやはりモジュールでの組み込みのような事が可能で、そ
れを真似るとこんな感じです。

print (
  header,
  start_html({"title" => "title"}),
    p("message"),
  end_html
)

最初の案に CGI.pm 風に head を start_html への組み込みを行うとこんな感
じでしょうか。

print (
  HTTP.header,
  HTML.start_html({"title" => "title"}) do
    HTML.p do
      "message"
    end
  end
)

イテレータを使用すると長くなりますが、この例での end_html のような終了
タグの出力忘れを文法的に防げるという利点があります。(もっとも、関数形
式にしても ((((())))) なんていう手もあるでしょうけれど。)

HTTP, HTML となっている所は CGI と置き換えて読んでもいいでしょう。
CGI.pm ではそのようになっています。

最初の案は長く見えますが、改行を減らしたり {} を使用したりるするとこん
な感じにもなるんですよね。

print(HTTP.header,
      HTML.start{
        HTML.head{ HTML.title{"title"} }
        HTML.body{ HTML.p{"message"} }
      })


-- 
青山 和光 Wakou Aoyama <wakou / fsinet.or.jp>