Catalyst::Manual::ActionsとCatalyst::Action系のモジュールの個人的な要約

Catalyst::Manual::Actions - Catalyst Reusable Actions - metacpan.org

DESCRIPTION

再利用可能なアクションについて。どう動くか。既存のアクションとあなたが書くアクションについて。アクションはメソッドの属性でメソッドコールの前後に機能する。共通に使用するアクションを記述する。

USING ACTIONS

簡単。よく使ってるディスパッチ用のアクション(LocalとかPrivateとか)と同じ感じだ。

  sub Hello :Local :ActionClass('SayBefore') { 
        $c->res->output( 'Hello '.$c->stash->{what} );
  }

この例ではHelloを実行する前にSayBeforeていうアクションを実行する。次のセクションで実装方法を示す。Catalyst::Actionネームスペース以外を使いたい場合は+を付けて"+Foo::SayBefore"みたいにする。または"MyAction('SayBefore')"みたいにする。

WRITING YOUR OWN ACTIONS

アクションを実装するのは簡単。Catalyst::Actionを継承してexecuteコールをデコレートする。

  package Catalyst::Action::SayBefore;

  use base 'Catalyst::Action';

  sub execute {
    my $self = shift;
    my ( $controller, $c, $test ) = @_;
    $c->stash->{what} = 'world';
    $self->NEXT::execute( @_ );
  };

  1;

アクションのあとになにかしたい場合は、executeコールのあとに書けばいい。

ACTIONS

Catalyst::Actions::RenderView

これはendアクションをデコレートする。Catalyst::Plugin::Default::Endとやってることは似てるけど、アプリケーションレベルじゃなくてアクションレベルでやるってところが違って、こっちの方がいいと思う。

    • -

こっからCatalyst::Action系のモジュールを見ていく。

Catalyst::Action::RenderView

Catalyst::Action::RenderView - Sensible default end action. - metacpan.org
1番目に利用可能なビューにフォワードする。ただしステータスが3xxの場合と、レスポンスボディがある場合を除く。また、デバッグモードのときにデバッグスクリーンを強制的に表示するためにURLにdump_info=1を渡せるようにする。
1つ以上のビューがある場合はコンフィグのdefault_viewを設定して指定することが可能。

METHODS

end - デフォルトのendアクション。アプリケーションクラスでオーバーライドする必要がある。

EXTENDING

レンダリングの前になにかしたい場合はendメソッドに書けばいい。

    sub end : ActionClass('RenderView') {
      my ( $self, $c ) = @_;
      # do stuff here; the RenderView action is called afterwards
    }

endアクションのあとになにかやるにはこうする。

    sub render : ActionClass('RenderView') { }

    sub end : Private { 
      my ( $self, $c ) = @_;
      $c->forward('render');
      # do stuff here
    }

属性をendアクションから外してもう一個メソッド作るんだね。
あとコードを見ると3xxだけじゃなくて204(no content)の場合も何もビューにフォワードしないみたい。

Catalyst::Action::REST

RESTのメソッドディスパッチを自動化する。

    sub foo :Local :ActionClass('REST') {
      ... do setup for HTTP method specific handlers ...
    }

    sub foo_GET { 
      ... do something for GET requests ...
    }

    sub foo_PUT { 
      ... do somethign for PUT requests ...
    }

メソッド名に_xxxを付けることでディスパッチ動作を変更する。
例えば/fooをGETしたときはfoo_GETにディスパッチされる。
メソッドが実装されてなかったら405(method not found)を返し、実装されてるリクエストメソッドの一覧をAllowヘッダに入れる。この動作はオーバーライド可能。

   sub foo_not_implemented {
      ... handle not implemented methods ...
   }

xxx_OPTIONSがない場合は自動的に200 OKで応答し、実装されてるリクエストメソッドの一覧をAllowヘッダに入れる。
あと必要なことはCatalyst::Controller::RESTを見てください。自動シリアライザ/デシリアライザもあります。
このモジュールを使うときはリクエストクラスがCatalyst::Request::RESTになります。

METHODS

dispatch - 以上のようなことをやるようにしてます。

Catalyst::Controller::RESTをちょっと見たけどシリアライザ/デシリアライザすげー便利そう。Content-type見てデータ変換してくれんのね。なるほど。

Catalyst::Action::Serialize

レスポンスデータのシリアライズ

    package Foo::Controller::Bar;

    __PACKAGE__->config(
        serialize => {
            'default'   => 'YAML',
            'stash_key' => 'rest',
            'map'       => {
                                'text/html'          => [ 'View', 'TT', ],
                'text/x-yaml'        => 'YAML',
                'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
            },
        }
    );

    sub end :ActionClass('Serialize') {}

HTTPレスポンスのボディをシリアライズする。シリアライザはHTTPリクエストのcontent-typeヘッダで決まる。
このActionはCatalystのコントローラのコンフィグに"serialize"エントリを持ってる必要がある。これはcontent typeとシリアライズクラスのマッピングをする。
それぞれのcontent-typeのシリアライズの詳細はCatalyst::Action::Serializeへのプラグインとして実装される。
一般的にはendメソッドでこのアクションを指定するけど、別に他のメソッドで指定してもかまわない。

  sub foo :Local :ActionClass('Serialize') {
     .. populate stash with data ..
  }

このモジュールを使うときはリクエストクラスがCatalyst::Request::RESTになる。

CONFIGURATION
  • default

デフォルトのシリアライズのフォーマット。リクエストされたcontent-typeを認識できなかった場合に使用される。

  • stash_key

シリアライズするデータの名前(stashの中の)。"rest"って値なら以下のデータがシリアライズされる。

$c->stash->{'rest'}
  • map

content-typeとプラグインとのマッピングをハッシュリファレンスで指定。

Catalyst::Action::SerializeBase

Catalyst::Action::SerializeとCatalyst::Action::Deserializeのベースクラス。
プラグインのロードとcontent-typeネゴシエーションを行う。
プラグインするのにModule::Pluggable::Objectというのを使用。

Catalyst::Action::Deserialize

リクエストデータのデシリアライズ

    package Foo::Controller::Bar;

    __PACKAGE__->config(
        serialize => {
            'default'   => 'YAML',
            'stash_key' => 'rest',
            'map'       => {
                'text/x-yaml'        => 'YAML',
                'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ],
            },
        }
    );

    sub begin :ActionClass('Deserialize') {}

このアクションはHTTPのPOST, PUT, OPTIONSリクエストのbodyをデシリアライズする。シリアライザはcontent-typeで決まる。
このActionはCatalystのコントローラのコンフィグに"serialize"エントリを持ってる必要がある。
結果は$c->req->dataに入る。これはCatalyst::Request::RESTがさくっと行う。
一般的にこのアクションはbeginメソッドに指定するけど、別に他のメソッドでもいい。

sub foo :Local :Action('Deserialize') {}

このモジュールを使うときはリクエストクラスがCatalyst::Request::RESTになる。

Catalyst::Action::Firebug

Firebug Liteのタグを挿入する。

    sub end : ActionClass('Firebug') {
        my ($self, $c) = @_;
        $c->forward( $c->view('TT') );
    }
    
    # or combination with Action::RenderView
    sub render : ActionClass('RenderView') {}
    
    sub end : ActionClass('Firebug') {
        my ($self, $c) = @_;
        $c->forward('render');
    }

というか、Firebug Liteというものの存在を初めて知りました。

    • -

Catalyst::Action::xxxについてはこんなところでしょうか。
http://search.cpan.org/search?query=catalyst%3A%3Aaction%3A%3A&mode=all
Catalyst::ActionChainというのがあるけどちょっととりあえず放置。