『モダンPerl入門』でも言及されているとおり、MVCのM、つまりモデルについては、ウェブアプリケーションフレームワークとは分離するのが定石です。
で、Arkの場合はこれまで以下のようにArkの管轄外のモジュールに代用させる処理を山のように書いていました。
package Amikeco::Web::Model::User
use Ark 'Model::Adaptor'; # automatically turn on strict & warnings
__PACKAGE__->config(
class => 'Amikeco::Logic::User',
);
1;
__END__
流石にこれを山のように書くのは辛いので、ラッパークラスでも作ろうかと考えていたのですが、Ark::Modelsの登場により、要はFlyweight的な面倒を見てくれるObject::Containerと仲良くすれば良いと分かったので、MyApp::Model以下のモジュールを殆ど全て消すことが出来ました。
今まで通りに$c->model('Foobar')のような感じで使うために、私は後述するように姑息な手だてを講じていますが、ファイルの数が多くなるよりはましだと思って楽をしてしまいました。委細は以下の通りです。
Amikeco::Web::Models
例によって、この記事では処理やらコメントやらPODやらを省いています。
package Amikeco::Web::Models;
use 5.010_000;
use Any::Moose;
extends qw(
Ark::Models
);
around 'register' => sub {
my ($next, $class, $model_name, $model_class) = @_;
$model_class //= 'Amikeco::Logic::' . $model_name;
$class->ensure_class_loaded($model_class);
$class->$next(
$model_name => sub { $model_class->new },
);
};
no Any::Moose;
__PACKAGE__->meta->make_immutable;
sub model {
my ($class, $model_name, $model_class) = @_;
$class->register($model_name => $model_class);
return $class->get($model_name);
}
Amikeco::Web::Controller::User
上同。
package Amikeco::Web::Controller::User;
use 5.010_000;
use utf8;
use Exception::Class::TryCatch;
use Amikeco::Web::Models;
use Ark 'Controller'; # automatically turn on strict & warnings
has '+namespace' => (
default => q{},
);
with qw(
Amikeco::Auxiliary::Localizable
);
__PACKAGE__->meta->make_immutable;
sub player
:Chained('/')
:PathPart('player')
:CaptureArgs(0)
{
my ($self, $c) = @_;
$c->forward('set_environment');
# $c->stash->{model}{user} = $c->model('User');
# これでもいいけど
# Amikeco::Web::Models->register( 'User' );
# $c->stash->{model}{world} = model('User');
# 面倒だからこれでいいや、という例
$c->stash->{model}{world} = Amikeco::Web::Models->model('World');
}
# ...
「ほぼ全廃」の余り
MyApp(この場合はAmikeco::Web)の以下の記述(A::P::A::Credential::Passwordのdigest_modeや、A::P::A::Store::Data::Modelのmodel)は、現状ではMyApp::Model以下と解釈されるので、今はしっかりMyApp::Model::User::Authentication::Digestなどが残っています。MyApp::Modelを完膚無きまでに根こそぎ廃止することが目的ではないので、今は取り敢えずこのままとしています。
package Amikeco::Web;
use Amikeco;
use Ark; # automatically turn on strict & warnings
use_plugins qw(
Authentication
Authentication::Credential::Password
Authentication::Store::Data::Model
Session
Session::State::Cookie
Session::Store::Memory
);
conf 'Plugin::Authentication::Credential::Password' => {
user_field => 'user_name',
password_field => 'password', # デフォルトと同じ
password_type => 'hashed',
digest_model => 'User::Authentication::Digest',
};
conf 'Plugin::Authentication::Store::Data::Model' => {
model => 'User::Authentication::Store',
target => 'user_authentication',
user_field => 'user_name',
};
# ...
CGIであればともかく、FastCGIやらServerSimpleやらといった環境では、不要な遅延ローディングになる(当該モデルを始めて使ったときにローディング時間分のペナルティがある)ので、上記は実はあまりいけていないです。
コメントする