そういえば CGI::Application::URIMapping
パストラック用に自作した CGI::Application::URIMapping が、1ファイル1コントローラーのディスパッチャ。各コントローラの先頭でマッピングを宣言すると、パッケージ名の basename を関数として呼び出す感じ。たとえば、MyApp::Users を register しておくと、MyApp::Users::users が呼び出される。
package MyApp::Users; use base qw/CGI::Application/; MyApp::URIMapping->register({ path => 'users/:category?', query => [ { name => 'order_by', omit => 'name', }, ], }); sub users { my $self = shift; # パーマリンク形式じゃなければリダイレクト return if $self->normalize_uri; ... }
上の例で言うと、指定したパーマリンク形式じゃなかったらリダイレクトとか、やってる。逆に、他のコントローラ (あるいはテンプレート) から、
my $uri = MyApp::Users->build_uri([ { category => $cat }, $self, ]);
とか呼び出すと、category の値だけを置き換え、他のパラメータは Users が宣言したもののみをコピーして、自動的にパーマリンクを作ってくれる。
ただ、当然、CGI::Application::URIMapping は、起動時に全コントローラの読み込みを行うので、CGI には向かない。
まあ http://kazuho.31tools.com/nanoa/nanoa.cgi の小規模から使えるウェブアプリケーションフレームワークという観点でいうと、ディスパッチテーブルとか受け付けるクエリパラメータの宣言とか重たいわけで、こういう機能は必須ではないのだろう、と。一方で、オプションとして提供するにはどうしたらいいか、という点は無考慮。
RoR っぽく、ディスパッチャを集中定義するのかなー。自分的には、CGI::Application::URIMapping のような各コントローラー内での分散定義のほうが、メンテナンス性が高いと思うんだけど。