テストスクリプトが綺麗にかけない
というかすごい汚くなる。うう。
抜粋
my $req = Test::MockObject->new;
my $res = HTTP::Response->new;
my $user_class = Test::MockObject->new;
my $params = {};
$res->{success} = 1;
$req->fake_module('Catalyst::Request');
$req->mock( params => sub {$params} );
$user_class->fake_module('Fake::User::Class');
$config->{user_class} = 'Fake::User::Class';
$c->mock( req => sub {$req} );
$c->mock( default_auth_store => sub { } );
$c->mock( set_authenticated => sub { } );
きも。。
--- /Library/Perl/5.8.6/HTML/FillInForm.pm 2005-10-14 05:49:09.000000000 +0900 +++ lib/HTML/FillInForm.pm 2006-01-06 15:45:37.000000000 +0900 @@ -83,6 +83,7 @@ if(my $file = $option{file}){ $self->parse_file($file); } elsif (my $scalarref = $option{scalarref}){ + $self->utf8_mode(1); $self->parse($$scalarref); } elsif (my $arrayref = $option{arrayref}){ for (@$arrayref){
とかしちゃった。その場しのぎ。
HTML::Parser の warning
Parsing of undecoded UTF-8 will give garbage when decoding entities at /Library/Perl/5.8.6/HTML/FillInForm.pm line 86.
とかってのが input エレメントの数だけ出てうぜええ。
helper
PACKAGE->config( name => 'AdminPage',
authentication => {
dbic => {
user_class => 'AdminPage::Model::DBIC::Account',
user_field => 'username',
password_field => 'password',
password_type => 'hashed',
password_hash_type => 'MD5',
},
},
authorization => {
dbic => {
role_class => 'AdminPage::Model::DBIC::Role',
role_field => 'role',
role_rel => 'map_account_role',
user_role_user_field => 'account',
},
},
session => {
expires => 3600 * 14,
storage => __PACKAGE__->path_to( 'session', 'session' )->stringify,
cookie_name => 'ap_sid',
},
validator => {
plugins => [qw/DBIC::Unique/],
options => { dbic_base_class => 'AdminPage::Model::DBIC', },
messages => __PACKAGE__->path_to('validator.yml')->stringify,
message_format => qq{<span class="error">%s</span>},
},
'View::TT' => {
CONTEXT => undef,
PRE_PROCESS => 'inc/macro.tt',
},
);
こんな config をちょくちょく書くんだけど、いまいちうまくヘルパーつくれなくてめんどいのよね。ううう。
なんつか、もうちょいアプリかかないとどこが共通でどこが変わるかとかがうまくわからんよ。パターん
CPAN Recent Changes
CPAN の Recent RSS は更新チェックにはつかえるけど、名前空間で絞りこみたかったり、何が変わったのか知りたいので、更新された部分の Changelog つきで RSS をはくツールを作ってみた。
などとすれば Catalyst::Plugin のみの更新もチェック可能。CPAN ウォーチャー必携!
ソースはこちら: http://svn.unknownplace.org/public/CPANRecent/trunk/
日付フィルタ
ここみたいに Path が /2005/12/27 とかからはじまっていた場合、それを日付情報としてパースし、それ以降の Path とともに default コントローラを呼ぶには
sub day : Regex('^(\d{4})/([01]?\d)/([0-3]?\d)(?:/(.*))?') {
my ( $self, $c ) = @_;
( $c->stash->{yr}, $c->stash->{mo}, $c->stash->{da} )
= @{ $c->req->snippets };
$c->forward( '/default', [ split '/', $c->req->snippets->[-1] ] );
}
sub month : Regex('^(\d{4})/([01]?\d)(?:/(.*))?') {
my ( $self, $c ) = @_;
( $c->stash->{yr}, $c->stash->{mo} ) = @{ $c->req->snippets };
$c->forward( '/default', [ split '/', $c->req->snippets->[-1] ] );
}
sub year : Regex('^(\d{4})(?:/(.*))?') {
my ( $self, $c ) = @_;
( $c->stash->{yr} ) = @{ $c->req->snippets };
$c->forward( '/default', [ split '/', $c->req->snippets->[-1] ] );
}
とかしなくちゃいけなくて(思い付かなくて) DRY すぎるのでなんとかしたい。
がんばればまとめられそうだけど、ううむ。
つか関係ないけど Regex コントローラはマッチした部分がコントローラの引数で飛んでくるって感じならいいのに。
むむ
create table playlist ( id integer not null, song integer not null, timestamp integer not null, primary key (id) );
create table song (
id integer not null,
name text,
artist integer not null,
album integer not null,
parimary key (id)
);
create table album (
id integer not null,
name text,
artist integer not null,
primary key (id)
);
create table artist (
id integer not null,
name text,
primary key (id)
);
とかって DB(SQLite) 構成で、
package DBIC::Playlist;
use base 'DBIx::Class::Core';
__PACKAGE__->belongs_to( song => 'DBIC::Song' );
package DBIC::Song;
use base 'DBIx::Class::Core';
__PACKAGE__->has_many( playlists => 'DBIC::Playlist' );
__PACKAGE__->belongs_to( artist => 'DBIC::Artist' );
__PACKAGE__->belongs_to( album => 'DBIC::Album' );
package DBIC::Album;
use base 'DBIx::Class::Core';
__PACKAGE__->has_many( songs => 'DBIC::Song' );
__PACKAGE__->belongs_to( artist => 'DBIC::Artist' );
package DBIC::Artist;
use base 'DBIx::Class::Core';
__PACKAGE__->has_many( songs => 'DBIC::Song' );
__PACKAGE__->has_many( albums => 'DBIC::Album' );
こうしたとして、ここで最新10件の playlist を取得したいとするとき、
my $playlists = DBIC::Playlist->search( {}, { order_by => 'timestamp desc', rows => 10 } );
とかすると $playlists->first->song
とか他のテーブルのもの読みにいくときにいちいち SQL が発行されるのであれよね。
ここで
my $playlists = DBIC::Playlist->search( {}, { order_by => 'timestamp desc', rows => 10, prefetch => [qw/song/] } );
とかすれば song テーブルは最初の SQL で JOIN して一緒に持ってきてくれる。
それはいいんだけど、その先の song.album とかもとってきてほしいんだけど、むりっすか!
この状況でたとえばテンプレート内で
[% WHILE (playlist = playlists.next) %]
album: [% playlist.song.artist.name %]
[% END %]
とかやると毎回 artist テーブルにクエリ投げる SQL がよばれるわけですよ。かっけぇ。。
どーすんのがいいのだろう。
FormValidator::Simple
Validator 使う機会があったら試してみようと思っていた FormValidator::Simple。やっと試してみた。
すげーいい!
けど、とりあえず軽く使ってみて一つ不満が。エラーメッセージを全体の集合でしか取れないこと。Data::FormValidator
みたいに個別かつフォーマットされた物もほしい。
とりあえず現状使う上では(Catalystの場合)、
MyApp->config(
'View::TT' => { PRE_PROCESS => 'inc/macro.tt', },
validator => {
messages => 'conf/messages.yml',
message_format => qq!<span class="error">%s</span>\n!,
},
);
などとし、macro.tt に
[%-
MACRO ERROR(action, key) BLOCK;
c.form.message.get(action, key, c.form.error(key)) | format(c.config.validator.message_format);
END;
-%]
とかしておいた上で、フォームのテンプレートで
<input type="text" name="user" id="login_form_user" value="" />
[%- ERROR('login', 'user') -%]
とかすげーめんどいことしてる。
モジュールのほういじろうかとおもったけど、いまいちうまい方法が思いつかなかったので。。
けどそれでも Data::FormValidator
よりは断然良い。
PERL5LIB
一時的に trunk 使いたいときとか
export PERL5LIB=`echo ~/workdir/Catalyst/**/lib(/) | sed -e 's/ /:/g'`
とかしてんですが、もっと簡単に書ける?>zsh
$|
$| = 1
したらちゃんとうごいた。