decadence

個人のメモ帳

Amon2 project template

Amon2を使う

こんな感じで使えば自分にとって使いやすいんじゃなかろうかってメモ
Response周り整理したい気がする
何かあれば適宜書き加えてく

基本

PLACK_ENV

  • deployment
  • development (default)
  • test

$ENV{PLACK_ENV}で管理されてる環境変数
起動時オプションは以下の通り.

plackup -E deployment app.psgi

静的ファイル

静的ファイルはpsgiファイル見ればわかるが,Plack::Middleware::Staticによって/static/に割り当てられてる.

mysql

config/$ENV{PLACK_ENV}.pl内に,DBI->connectに渡す各引数を記載
DBIにはDBIx::Sunnyを利用.関数名が直感的で良い.SQL::NamedPlaceholderとか使って拡張した独自のDBI使っても良い.
DBIx::Sunnyとか継承させたものをHoge::DBIとすると,Hoge::DBI::dbをuse parent -norequire => 'DBIx:Sunny::db'で作りselect_oneとか独自実装,Hoge::DBI::stをuse parent -norequire => 'DBIx::Sunny::st'で作る.後は下のRootClassで読み込ませる.

+{
    'DBI' => [
        "dbi:mysql:database=fuga", 'username', 'password',
        +{
            RootClass         => 'DBIx::Sunny',
            mysql_enable_utf8 => 1,
        }
    ],
};

setup

cpanfileに依存書く.

carton install
mysql -uusername -p fuga < db/mysql.sql

最初にする事

作る

amon2-setup.pl --flavor=Basic Hoge

lib/Hoge/Web以下に3つのフォルダ作成

cd Hoge/lib/Hoge/Web
mkdir C Model Service

Routing

H::W::Dispatcherを以下のように変更

- use Amon2::Web::Dispatcher::Lite
+ use Amon2::Web::Dispatcher::RouterSimple;

+ use Hoge::Web::C::Root;

+ connect '/'   => 'Root#index';

Root#indexはこんな感じ

sub index {
    my ($class, $c) = @_;
    return $c->render('index.tt');
}

A::W::D::RouterSimpleはRouter::Simple - search.cpan.orgこっち見れば大体いける.

MVC

Controller

Hoge::Web::C以下に記述

Model

Hoge::Web::Model以下に記述
テーブルモデル(+データモデル)

Service

Hoge::Web::Service以下に記述
DBアクセス

View

tmplの中に.出力するものは.html,wrapper,includeするものは.ttにする

テスト

全てのテストで読み込む汎用パッケージを用意する.Amon2ではt::Utilがあるから,これを読み込む
以下のような記述があるため,これでtest時はtest用のdatabaseを参照するようになる.

BEGIN {
    $ENV{PLACK_ENV} = 'test';
}
  • 参考

共通してuseするものとか書いておくと楽
Hatena-Textbook/db-control-by-dbi.md at master · hatena/Hatena-Textbook · GitHub

Middleware

適当にlib以下にPlack::Middleware::MyMiddlewareとか作る
Plack::Middleware継承させて,前処理はprepare_appに,毎回呼ばれる処理はcallで定義.
後はapp.psgiでenableするだけ.引数のハッシュはそのままMyMiddlewareのselfから呼び出せる

その他

Context関連

redirectとか色々
$c->redirect('/foo', +{bar => 3})

取り敢えずドキュメント見る.Amon2::Web - search.cpan.org

rendering
  • render_json

Web.pmのload_pluginsに'Web::JSON'を付け加えるとContextからrender_jsonが呼べる.
Amon2::Plugin::Web::JSON - search.cpan.org
Web.pmに直接実装加えても良さそう.その場合はContextからcreate_response使って組み立てる感じ.

jsonの型付けにはJSON::Types - search.cpan.orgを使おう

Context拡張

Hoge::Web::Base.pmにWeb.pmの中身移して,Web.pmを拡張として用いるのが良さそう.
(Hoge::Web::Context.pmにWeb.pm継承させてapp.psgiで読み込ませたら出来そうだったけどできなんだ...)

  • パラメータ周り

wantarray使って複数値と単一値のどちらを取るか決めるみたいなのしてみたけど,Perl Monger的にはどうなんだろう.使いやすいっちゃ使いやすいと思うのだが.

sub string_param {
    my ($self, $key) = @_;

    if (wantarray) {
      map {decode_utf8 $_} $self->_parameters->get_all($key);
    }
    else {
      decode_utf8 $self->_parameters->get($key) // "";
    }
}

sub _parameters {
    my $self = shift;

    $self->{_parameters} //= do {
        my $query = $self->request->query_parameters;
        my $body  = $self->request->body_parameters;
        my $path  = Hash::MultiValue->new(%{$self->{args}});
        Hash::MultiValue->new($query->flatten, $body->flatten, $path->flatten);
    };
}

追記

毎回考えるの面倒だし,自分用のAmon2のFlavor作った
一応使えるけど,目下改良中
krrrr38/Amon2-Setup-Flavor-Krrrr · GitHub