当初は3日くらいで次の人に回すつもりだったのですが、なんだかんだで機能追加してるので5日くらい書かないといけないのではないか戦々恐々としてるkanです。
昨日は http://localhost:5000/ へアクセスすると「hello」と表示されるようになったので、いよいよ本格的に作っていくことにします。まず、ページの構成をどうするか考えます。最初、こんな感じに考えました
更に、複数のtrackを扱うのでtrackの一覧を出して欲しいということになり
年/ で、その年のtrack一覧を表示するようにしました。
これを実現するには、アクセス毎に処理を振り分ける必要があります。CPANにはpath routing用のモジュールが沢山ありますが、今回はシンプルに使える Router::Simple を使うことにしました。↑のルールは以下のように書けます。
$router->connect( '/{year:\d{4}}/', { controller => 'Calendar', action => 'track_list' } ); $router->connect( '/{year:\d{4}}/{name:[a-zA-Z0-9_-]+?}/', { controller => 'Calendar', action => 'index' } ); $router->connect( '/{year:\d{4}}/{name:[a-zA-Z0-9_-]+?}/{day:\d{1,2}}', { controller => 'Calendar', action => 'entry' } );
「{year:\d{4}}」のように書くと「\d{4}」という正規表現にマッチした値を「year」というキーで参照できるようになります。以下のような感じです。
my $p = $router->match($env); warn $p->{year};
処理を振り分けたら、画面を表示する処理を作ります。HTMLを出力する場合、perlのソース中にHTMLを埋め込んでいく手もありますが、可読性が落ちて早々にメンテが困難になるケースが多いと思います(e.g. perl4時代のCGIスクリプト)。そういった理由から個人的にはなるべく最初からテンプレートをコードと分離するようにしています。
分離したテンプレートはplain textで書いて正規表現で置換、とかでも良いのですが、どうせ誰かすぐ使うだろうということで、今をときめく Text::Xslate を使ってしまうことにしました。Text::Xslate::Syntax::TTerse を使ってTT2風の構文で記述することにします。
my $tx = Text::Xslate->new( syntax => 'TTerse', path => ['tmpl', 'app/tmpl'], cache_dir => '/tmp/app-adventcalendar', cache => 1, function => { uri_for => sub { my($path, $args) = @_; my $uri = $base->clone; $uri->path($conf->{base_path} . $uri->path . $path); $uri->query_form(@$args) if $args; $uri; }, }, );
pathに↑のように複数のディレクトリを指定しておくと、基本的に app/tmpl の下にテンプレートファイルを置くけど、tmpl/ の下に置くとそっちを使うようにする、みたいなことが出来て便利ですね。
シンプルなテンプレートを表示して満足したので明日に続きます。