Amon2でModel作ってControllerから呼ぶ

MVCが良いか悪いかは兎も角、、
ViewとControllerしかないので、Modelを作ってみます。
Amon2のサンプル的なやつだと、Controllerから直接dbを叩いてるようなのがよくあるんですけど、Controller肥大化を避ける意味でも。
(Catalystで言うところの、Catalyst::Model::DynamicAdaptor(MultiAdaptor)的な動きが個人的には好みですw)

以下、個人的メモ。

MyApp::Modelってプラグインを作成。

package MyApp::Model;

use strict;
use warnings;

use File::Basename;
use lib sprintf("%s/lib", dirname(__FILE__));

use Amon2::Util;
use Module::Find;

sub init {
    my ($class, $c) = @_;

    my $model = undef;
    my @model = usesub MyApp::Model; # MyApp::Model::以下をuse
    for ( @model ) {
        my $name = $_;
        $name =~ s/^MyApp::Model:://;
        $model->{ $name } = $_->new({ config => $c->config }) if $_;
    }

    # $c->modelを追加
    Amon2::Util::add_method(
        $c,
        'model',
        sub {
            $_[0]->{'model'} ||= $model;
        }
    );
}

1;

これでMyApp::Model以下のモジュールをnewしたものが、$c->model->{‘xx’}で呼べるはずです。

呼ばれるやつは下。

package MyApp::Model::User;

use strict;
use warnings;

use Object::Simple -base;
has [qw/config/];

sub find_name {
    my ( $class, $args ) = @_;

    return 'hogehoge';
}
1;

コンストラクタは、Object::Simpleを使ってますけど、
Class::Accessor::Lite(Fast)でも、Mooseでも好きなやつで。

上で作ったプラグインを追加

package MyApp;
use strict;
use warnings;
use utf8;
our $VERSION='0.01';
use 5.008001;

use parent qw/Amon2/;

__PACKAGE__->load_plugin('+MyApp::Model');

# Enable project local mode.
__PACKAGE__->make_local_context();

1;

先頭の+をつけない場合は、Amon2::Plugin::***になってしまいます。
今回は自分で勝手に作ったやつなんで、先頭に+をつけます。

Controllerから叩く。

package MyApp::Web::C::Root;

use strict;
use warnings;
use utf8;

sub index {
    my ( $class, $c ) = @_;

    my $user_name = $c->model->{'User'}->find_name({ user_id => 1234 });

    return $c->render('index.tx');
}

1;

DBの接続(切断)まわりは検討中。。
多分、この辺りかな?

package MyApp::Web;

__PACKAGE__->add_trigger(
    BEFORE_DISPATCH => sub {
        my $c = shift;
        # DB接続
    },
    AFTER_DISPATCH => sub {
        my ( $c, $res ) = @_;
        # DB切断
    }

追記

cpanにはまだ上がってないみたいですけど、githubにAmon2::Plugin::Modelがありました。。。
Amon2::Plugin::Model
あとで試してみよ。