たろマーク (はてなブックマーク)
-
[ django ] view を class based で書けるようになってた。
- Colorful Bokeh Effect in Pixelmator | Abduzeedo | Graphic Design Inspiration and Photoshop Tutorials
[ pixelmator ] -
[ pixelmator ]
■ 最近の Catalyst の構成
最近 Catalyst のエントリをよく見かけるので自分の構成をさらしてみます。コードは CodeRepos にあります。
share - Revision 30441: /lang/perl/Chaostr/trunk
元々は、作ろうとしたアプリがあったんですが、去年の Catalyst confernce 以降、MyApp 的実験場になってます。仕事で作ったものはさらせないので、構成だけ表に出す感じ。ちなみに今のところ Catalyst 5.7 系でしか使ってないです。
あと、Controller クラスのベースで Resources を使ってるけど、自分のやり方は推奨されない使い方をしてます。新規投稿や編集画面用の URL を作るために一度自前 Base クラスを噛ませてたんですが、new, edit はデフォールトであります。Resources の使い方とかはこっちに書きました。
クラス構成
現在の構成をざっと図にするとこんな感じです。
Config, Log, DB, Validator を Catalyst から切り離して Service(Logic) クラスでも直接扱えるようにしてます。
PseudoRequest については後述。
Chaostr::Class / Chaostr::Role
このあたりは、Angelos インスパイアです。と言うか最初はまるパクリだったw
Angelos::Class は Mouse ですが、Chaostr::Class は Any::Moose で、呼び出し元が Moose だったら、Moose、そうでなければ Mouse になります。Cat 5.8 系で Moose になってもいいようにと。test やコマンドラインからは Mouse がいいなぁと言う感じで。
Chaostr::Class::* は Service クラスで mixin して使用するクラスです。
config, log, db, validator とかも mixin されてます。mixin はこんなやり方でいいのかがちょっとわからない。
Chaostr::Config
tomyhero さんが書いてる CatalystとConfig - perl-mongers.org を見てもらうとわかると思います。
Config::Multi を singleton 化して、どこでも使えるようにしてるよ!
すこし違うのは __path_to()__ とか __uri()__ とかで Path::Class や URI オブジェクトになる点くらい。
Chaostr::Log
Log::Dispatch::Config 使ってます。
extlib に Log::Dispatch::Configurator::Hash というのをこさえてあって、hash から Log::Dispatch::Config::Configurator オブジェクトを作れるようにしてます。
開発中は Log::Dispatch::Colorful を使ってます。Log::Coloful は、Log::Dispatch のメソッドいじったりしてるので、Dumper が必要ない人は yappo さん作の Log::Dispatch::Color 使うといいよ。
$Log::Dispatch::Config::CallerDepth で呼び出し元からの深さを指定してるんだけど、Service から呼んだときと、Catalyst から呼んだときでエラー元の表示が変わってしまってるのが少し悩み。
Validator
FormValidator::LazyWay 使ってます。validator は Catalyst にあればいいかと思ってたんですが、Service クラスに Request を渡しているので Service クラスで validate できても良いなぁと思って切り離してます。
どっちでもできるようにしておいて、なるべく Service 側でできるようにという感じ。
DB
DBIx::Class です。これも Catalyst::Model::Schema::DBIC とかは使わずに自前 Singleton 化して Service クラスでも呼び出せるようにしてます。
Model
Catalyst::Model::MultiAdaptor を使用して、Service クラスが読み込まれる用にしています。
MultiAdaptor は、いくつかの LifeCycle をサポートしてますが、LifeCycle::Singleton に手を入れた LifeCycle::SingletonPerRequest っていうのを作って使ってます。
これは起動時に指定したクラスを require して instance 化するまでは同じですが、その instance 内でリクエスト毎に $c->request と $c->session が Service クラス側のアクセッサに渡ってくるようになってます。
sub install {
my $self = shift;
my $instance = $self->create_instance( $self->adapted_class, $self->config );
Sub::Install::install_sub(
{ code => sub {
my ( $component, $context ) = @_;
$instance->request($context->req);
$instance->session($context->session);
return $instance;
},
into => $self->model_class_name,
as => 'ACCEPT_CONTEXT',
}
);
}
もうね、Model として切り分けたときに request とか session をいちいち渡すのが面倒になって、「自動で全部渡してしまえ」と思った末の結果です。あとは、メソッド側で使いたいのだけ使えよと。
引数として必要な分だけ渡すと言う作りもできるよ。
後は、FormValidator::LazyWay を validator として使ってます。
validate は Catalyst 側でやればいいと思うんですが、作ってて Service 側でもやりたくなったら使おうくらいの考えで搭載しました。
CLI と test
Model のところ読んで、結局 Catalyst 依存してるじゃんかと思われるかもしれませんが、hash を渡すと request オブジェクトに変えてくれる PseudoRequest というクラスをこさえて、CLI や test も Service クラスを使えるようにしてます。
PseudoRequest にファイルの場所とか教えると $self->request->upload 的なこともできるので、ファイルアップロードのテストまで書けるようにはしたつもり。
参考
参考にしたというか、大元は avmaster さんのAV女優ブログ検索のソースで、この一年ぐらいちまちま育ててた感じです。






