The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

Pickels Web Framework

Pickles とは?

Sledge を微妙に意識した、Web Application Framework です。以下のような点が特徴です。

インストール

いつもと一緒です。

% perl Makefile.PL
% make
# make install

Hello World!

インストールすると pickles-setup コマンドがインストールされます。

% pickles-setup MyApp

Module::Setup を使用しているので、名前とかメールアドレスとか聞かれます。

MyApp に以下のようなレイアウトでファイル群が作られます。

MyApp/
    Changes
    MANIFEST.SKIP
    Makefile.PL
    README
    MyApp.psgi 
    config.pl - 設定ファイル
        htdocs/ - 静的ファイル
        lib/ - アプリケーション本体
            MyApp.pm 
            MyApp/
                Config.pm
                Container.pm
                Context.pm
                Dispatcher.pm
                View.pm
            Controller/
                Root.pm
        t/ - テスト
        view/ - テンプレート類
        xt/ - 開発者用テスト

インストール時点では View を表示するだけのアプリケーションが http://localhost:5000/ で立ち上がります。

% cd MyApp
% plackup -I./lib MyApp.psgi

アプリケーションの書き方

基本的な流れは

  1. MyApp::Dispatcher を更新し、URL に対応した Controller と action を指定
  2. MyApp::Controller::* を追加、編集して実際のロジックを記述
  3. その他必要に応じてプラグインのロードを MyApp::Context で行う

Dispatcher

Dispatcher は MyApp/etc/routes.pl ファイルを読み込みます。 パスと Controller, action の対応を DSL で記述します。 routes.pl のシンタックスの詳細は Router::Simple::Declareを参照してください。

router {
    connect '/' => { controller => 'Root', action => 'index' };
    connect '/add' => { controller => 'Root', action => 'add', };
    connect '/:id' => { controller => 'Root', action => 'go' };
};

内部的には Router::Simple を使っています。 パスの一部を引数として使用する場合は $c->args で Hash-Ref としてアクセス出来ます。

Controller

package MyApp::Controller::Root;
use strict;
use warnings;
use parent 'Pickles::Controller';

sub index {
    my( $self, $c ) = @_; # $c is-a MyApp::Context
}

sub view {
    my( $self, $c ) = @_;
    my $id = $c->args->{id};
    # ...
}

1;

__END__

Config

設定ファイルとして HASH-Ref を返す .pl ファイルを使用します。デフオルトでは MyApp/etc/config.pl が読み込まれます。 値へのアクセスは get メソッドを利用するか、HASH-Ref として直接アクセスする事も出来ます。get メソッドの場合は第2引数でデフォルト値を指定する事が出来ます。

my $config = MyApp::Config->new;
my $val = $config->get('foo', 2); # デフォルト値を指定
my $val = $config->{'foo'};

2種類の環境変数を参照します。

HOME

デフォルトでは pickles-setup で作成した MyApp 直下がHOMEとなり、アプリケーションで使用するあらゆるファイルはHOMEの下に配置します。 通常はHOMEを明示的に指定する必要は無いでしょう。 アプリケーションを make install した場合等、アプリケーションのHOMEを明示的に指定したい場合は $ENV{'MYAPP_HOME'} もしくは $ENV{'PICKLES_HOME'} という環境変数に HOMEを絶対パスで指定します。 HOMEの値は $config->home で取得する事が出来ます。

path_to

HOME からの相対パスを絶対パスに変換して返します。

my $view_dir = $config->path_to('view');

複数の設定ファイルの読み込み

環境変数を元に複数の設定ファイルを読みこみ、マージする事が出来ます。

$ENV{'MYAPP_CONFIG'} が存在する場合は etc/config.pl の代わりにその値をベースの設定ファイルとして読み込みます。 / から始まる場合は絶対パスとして扱い、/ から始まらない場合は HOMEからの相対パスとして扱い、$config->path_to を経由して読み込みます。

その後、環境変数 $ENV{'MYAPP_ENV'} が存在する場合はその値を suffix として設定ファイルが読み込まれ、マージされます。

例)

$ENV{'MYAPP_CONFIG'} = undef;
$ENV{'MYAPP_ENV'} = 'test';

MYAPP_HOME/etc/config.pl
MYAPP_HOME/etc/config_test.pl 

の順に読みこみ。

$ENV{'MYAPP_CONFIG'} = '/path/to/foo.pl';
$ENV{'MYAPP_ENV'} = 'test';

/path/to/foo.pl
/path/to/foo_test.pl

の順に読みこみ。

Context

package MyApp::Context;

use strict;
use warnings;
use parent 'Pickles::Context';

__PACKAGE__->load_plugins(qw(Encode));

1;

__END__

Container

Pickles は Model の機構を持ちませんが、Webアプリケーション、CLI から共通で使用するコンポーネントを登録して再利用するための仕組みとして Container クラスが用意されています。

package MyApp::Container;

use strict;
use warnings;
use parent 'Pickles::Container';
use DBI;

__PACKAGE__->register( Model => MyApp::Model->new );
__PACKAGE__->register( DBI => sub { DBI->connect(...); } );

1;

__END__


Webアプリケーション

sub index {
    my( $self, $c ) = @_;
    my $dbh = $c->get('DBI');
    # ...
}


CLI

my $container = MyApp::Container->new;
my $dbh = $container->get('DBI');
$dbh->prepare(...);

プラグイン

デフォルトでは文字エンコーディングを適切に取り扱うための Pickles::Plugin::Encode をロードしています。

挙動のカスタマイズは Context を拡張する事によって行います。 Context の拡張は主に継承によるメソッドの追加、オーバーライド、Class::Trigger によるフック関数の実行によって行います。