TTSiteで謎の空白行

相変わらずCatalyst。Adding RSS feedsを参考にTTSiteでRSS出力。

が、なぜかファイルの先頭に謎の空白行が。

XML パースエラー: 外部実体の初めに XML 宣言がありません。
URL: http://localhost:3000/rss/bookmarks/kzfm
行番号: 2, 列番号: 1:<?xml version="1.0" encoding="UTF-8"?>
^

root/lib/config/colが原因だった。

[% site.rgb = {
     black  = '#000000'
     white  = '#ffffff'
...
      error   = site.rgb.red
   };
-%]

とやって解決。

あと、rss用のテンプレート指定したときにヘッダーフッター入らないようにroot/lib/site/wrapperに書いておく。

[% IF template.name.match('\.(css|js|txt|rss)');
     debug("Passing page through as text: $template.name");
     content;
   ELSE;
     debug("Applying HTML page layout wrappers to $template.name\n");
     content WRAPPER site/html + site/layout;
   END;
-%]

flashの使い方

Catalystのflashは意外に使えるやつだった。

$c->stash->{XXX}

のようだがredirectしても使える。ただし、一度読むと消えてしまう。

なんかの操作をした後、メッセージと共にredirectしたいときとかに使うとよさげ。

Controllerでやるべきかテンプレートに送るべきかわからんたいだ

User:Bookmarkみたいな1対多(多対多でもいいけど)なテーブルをDBICでいじるとする。

DBICをスクリプトなんかでいじくるときには、Perl/DBIC - Nekokak's core dump な感じでいいんだけど、、、、

CatalystでDBIC+TTを使う場合に、どこまでコントローラーで処理すればいいのか分からなくて悩んでる。

http://localhost:3000/bookmark/kzfm

みたいに、ユーザーのブックマークを表示したいときに

sub test1 : Private {
    my ($self, $c, $user) = @_;
    my $uid = $c->model('PblDB::User')
            ->find({empnum => $user})->id;
    my $b =
        [$c->model('PblDB::UserBookmark')->search(user_id => $uid)];
    my @bookmarks = map $_->bookmark_id, @$b;
    $c->stash->{bookmarks} = 
       [$c->model('PblDB::Bookmark')->search(id => \@bookmarks)];
    $c->stash->{template} = 'bookmarks/list.tt2';
}

これはイマイチというか駄目やろ(何のためにDBICのリレーション設定したのかわからんようになる) というのは分かるんだけど、下のやり方もなんか変。

sub test2 : Local {
    my ($self, $c, $user) = @_;
    $c->stash->{user} = $c->model('PblDB::User')
      ->find({empnum => $user});
    $c->stash->{template} = 'bookmarks/test.tt2';
}

で、テンプレートのほうは、user受け取ってbookmarkを取り出すと。

[% FOREACH bookmark = user.bookmarks -%]
<ul>
  <li>[% bookmark.id %]</li>
  <li>[% bookmark.title %]</li>
</ul>
[% END -%]

とかやると、処理がコントローラーとテンプレートにまたがっちゃうし、ページの処理とか面倒になっちゃう。

DBICのオブジェクトは渡さずに、コントローラー内で全部処理してハッシュをTTに被せるだけにするのがいいのかなぁ。

ウーム悩ましい(僕だけ?)

07.01.18 追記

コメント見て、なるほどと思ったのでこうしてみた。そのうちイテレータにする。

    defined($user)                                            ? #
    $c->stash->{bookmarks} = [$c->model('PblDB::User')       #
                             ->find($user->id)->bookmarks]   : # user exist
    $c->response->redirect('/bookmark/')                       ; # or not

ユーザーがいない場合には、インデックスにリダイレクトするようにした。

07.01.22 追記

モデルでやるべし。というコメントを見て、ふむー、ResultSetってそのためにあんのかとか思った。開放された気分。DBIC好きになってきた。

DBICで(多対多)対多

相変わらずCatalyst,DBICと戯れてる。で、テーブルも複雑になってくると。

今回こんな感じのテーブルを扱ってみたが、なかなかうまく書けん。

m2m2m

User,Bookmarkからサーチする場合

うまい書き方が分からないので、リレーション張らんでもええような、ベタベタな構文になってしまう。

勝手に二重のイテレータみたいになってくれればいいのに。

Tagからサーチする場合

my $ub_it = $c->model('PblDB::Tag')->find($tag->id)->user_bookmarks;
while(my $user_bookmark =  $ub_it->next){
    $item->[$i]->{'title'} = $user_bookmark->bookmark->title;
    $item->[$i]->{'abstract'} = $user_bookmark->bookmark->abstract;

my $tag_it = $c->model('PblDB::UserBookmark')
    ->find($user_bookmark->id)->tags;

みたいにuser_bookmarksテーブルのイテレータをまわさないといけないのだろうか?

ここらへんのも参考にする。

Catalystでいくつかメモ

redirectではまった。

$c->response->redirect($c->uri_for('/'));

でdetachみたいに処理が戻ってこないと勘違いしてたので、気付くのに時間がかかった。

Regex,LocalRegex

Regexの受け取りが

$c->req->snippets

でなく、

$c->req->captures

になってた。

HTML::Widgetの使い方がいまいち

ちゃんと読む

/Manual/Tutorial/AdvancedCRUD

TTSiteをいじってみた

Catalyst::Manual::Tutorial::CatalystBasics

script/myapp_create.pl view TT TT

ではなく、

script/myapp_create.pl view TT TTSite

とやれと。これにより、ちょっとした雛形も一緒に作成されるので、ちょっと便利になったかなと。

で、TTSiteってどうなってんだろうかと、root/lib/siteを眺めてみたら、WRAPPERというしらない構文があったので。

Catalyst::Helper::View::TTSite と TT の AutoWrapper : おまえのログ

WRAPPER オプションに一番外側になるテンプレートを指定すると、tt_process で生成される出力が、WRAPPER で指定したテンプレの content になる

おー、入れ子にするには便利な機能だ(WRAPPER)。

TTSiteはヘッダ、フッタはPROCESSで埋め込んで、bodyの中身をWRAPPERで埋め込むと。図にするとこんな感じ。

TTsite

Perl Template Toolkitが気になるが、

ProductName Perl Template Toolkit
Darren Chamberlain
Oreilly & Associates Inc / 3031円 ( 2004-03 )


Template Toolkit Manual -テンプレートツールキット和訳マニュアル-も読み返そう。

Catalyst Advent Calendar

集中して読んだ。

  • catalystでpdfを作成
  • Day 12
  • catalystでmp3ストリーミング再生
  • Day 15
  • ApacheでFastCGIをつかってCatalystを動かす
  • Day 16
  • Google Maps Mashup
  • Day 23

が、参考になった。Google Maps API面白いのであとでなんかやってみよう。(と思ったが、なかなか思い浮かばん)

あとはTemplate::Latexでpdf化するのは結構良いかも。埋め込むだけだし。clmemoからpdfにできるようにしたいかも。

TTSiteがうごかねーと悩んでいたら

久々にtelnetしたマシンでcatalystをいじってたら、TTSiteがうまく動かず、おかしいなぁ~と思ってたら

Catalystのバージョンが5.6902だった

このバージョンでTask::Catalyst 1.90を入れたので、エラーメッセージを吐かずに真っ白画面を出力していた模様。

Catalyst 5.7006にバージョンあげたらちゃんと動いた。

で、TTSiteだけど、普通に使うTTのヘルパーモードだと

app_create.pl view TT TT

で、TT.pmを作ってくれるだけなのに対してTTSiteは、

app_view TT TTSite

とやってヘルパーさんを動かすと、ヘッダー、フッターとかのテンプレートの雛型も一緒に作ってくれるという、お手軽度50%増量みたいな感じらしい。さらに、コントローラのディレクトリ構成とテンプレートのディレクトリの構成が対応するっぽいのでテンプレートが増えたときに把握しやすいのかも。

っていうか、これから使おうとしているのでまだちゃんとわかってないけど。

あとは、TTSiteだと拡張子がtt2になるので、Meadowのttモードも動くように.emacsに設定を追加しておく。

(setq auto-mode-alist
     (cons
       '("\\.tt2$" . html-helper-mode) auto-mode-alist))

Catalyst::Manual::Tutorialが充実してた

あれ、ちょっと見ない間に、チュートリアルが充実してた。

Catalyst::Manual::Tutorial

色々新しいことが書いてた。

  • DefaultEndはやめてCatalyst::Action::RenderView使うべし
  • TTSiteの使い方
  • CRUDをDBICで
  • AuthenticationとAuthorizationのやり方
  • デバッグとテスト
  • HTML::Widgetの使い方
  • flash featureの説明というか使いどころ

あたりは読んだけど、実際に何か作ってみないとちゃんと理解してるのかわからん。というわけで、DBICで多対多のdb使ってpubmed用のsbsを作り直してみることにした。Wikiに少しずつ書いてく予定。

CatalystのTTでeval_perl

Catalystの設定ファイルのyamlにEVAL_PERLを入れておくとTTでperlのコードが使える。

      INCLUDE_PATH:
              - 'root/templates'
      TEMPLATE_EXTENSION: '.tt'
      EVAL_PERL: 1

とかやっておくと

[% PERL %]
    print $stash->{tags};
[% END %]

みたいに書ける。

やりたいことはちょっとした加工だったので、ホントはvirtual method使いたかったのだけど、catalystのどの部分でdefine_vmethod呼べばいいのかイマイチわからなかった。

それにしてもTTでperlのコード書くのはちょっと気持ち悪い。