forwardとdetach
forwardとdetachメソッドは、どちらも呼び出し先のアクションを実行しますが、それぞれの違いは、forwardメソッドが呼び出し元に処理が戻ってくるのに対して、detachは呼び出し先アクション実行後に呼び出し元アクションには戻ってきません。また、forwardメソッドでは、呼び出し先アクションからの戻り値を受け取ることもできます。それぞれの用途として、forwardは、ある程度のまとまりを持ったデータを処理するために呼び出したり、入力値のチェックを行う場合などに使用します。
それに対してdetachでは、リクエスト処理を中断させることができるため、未ログインの場合にログインフォームにとばしたり、エラー発生時に独自のエラーページを表示させたりする場合などに使用します。
forwardとdetachメソッドの使い方
forwardとdetachのメソッドは次のように引数を指定して呼び出します。
# (1)アクション名を指定
$c->forward('/foo/bar/baz');
$c->detach('/foo/bar/baz');
# (2)クラス、メソッド名を指定
$c->forward('MyApp::Controller::Foo::Bar', 'baz');
$c->detach('MyApp::Controller::Foo::Bar', 'baz');
# (3)なにも指定せず呼び出す(detachのみ)
$c->detach();
(1)アクション名を指定
同じコントローラに属するアクションを呼び出す場合には$c->forward('do_action')や$c->detach('do_action')のようにアクション名だけを指定します。異なるコントローラのアクションを呼び出す場合には、この例のようにネームスペースを含めた形式で、スラッシュ(/)から始まるアクション名を指定します。
また、$c->forward('/foo/bar/baz', [qw/aaa bbb ccc/])のように、引数を配列として渡すことができます。この場合、呼び出し先からは$c->request->args経由で引数を取得できます。detachの場合も同様です。
(2)クラス、メソッド名を指定
アクションのクラス(モジュール)名とメソッド(サブルーチン)名を指定して呼び出すこともできます。メソッド名はアクションのメソッド名を指定する必要があります。例えばsub not_action {}のようにアクションではないメソッドは指定することができません。
また、メソッド名を省略してクラス名だけを指定することもできます。例えば$c->forward('MyApp::View::TT')のように呼び出すこともできますが、この場合に指定可能なクラスは、Catalyst::Componentを継承したクラスである必要があり、process()メソッドが呼び出されます。クラス、メソッド名を指定する呼び出しの場合でも、アクション名を指定した場合と同様に、引数を配列として渡すことができます。
(3)何も指定せず呼び出す(detachのみ)
detachでは、3番目の例のように引数無しで呼び出すことができます。この場合には、直ちに処理チェーンを抜け出して、関連するendアクションが呼び出されます。
visitとgo
forwardとdetachメソッドでは別アクションのみを実行しますが、visitとgoアクションでは、beginやautoなどの組み込みアクションが定義されている場合には、呼び出し先アクションが実行される前にこれらの組み込みアクションが呼び出されます。それぞれの違いは、visitでは呼び出し元アクションに処理が戻ってくるのに対して、goでは呼び出し先アクションの処理が終了した後に呼び出し元アクションに戻ってきません。
Catalyst::View::TTを使用する場合では、アクションで明示的にテンプレート名が設定されていないと、デフォルトの動作として、実行されたアクションの「アクション名.tt」をテンプレートファイルとして扱います。forwardやdetachでは実行アクションは呼び出し元アクションになるため、呼び出し先テンプレートを使用する場合には明示的にテンプレートファイル名を設定する必要があります。visitやgoでは実行アクションが呼び出し先アクションになるため、呼び出し先アクションのアクション名と同じ名前のテンプレートファイルを用意しておけば、明示的にテンプレートファイル名を設定する手間を省くことができます。
このことから、非常に多くのテンプレートファイルを使用する場合には、visit/goメソッドでアクションを呼び出すという決まりを作っておけば、アクション名とテンプレートファイル名の関係だけを管理すればよくなります。
visitとgoメソッドの使い方
visitとgoメソッドでは次のように引数を指定して呼び出します。forwardやdetachメソッドではビューやモデルクラスを指定することもできましたが、visitやgoでは、コントローラ以外を指定することはできません。
# (1)アクション名を指定
$c->visit('/foo/bar/baz');
$c->go('/foo/bar/baz');
# (2)コントローラのクラス、メソッド名を指定
$c->visit('MyApp::Controller::Foo::Bar', 'baz');
$c->go('MyApp::Controller::Foo::Bar', 'baz');
(1)アクション名を指定
アクション名の指定方法は、forwardやdetachと同じです。この場合にも次のような形式で2種類の引数を渡すことができます。
my @captures = qw/aaa bbb ccc/;
my @arguments = qw/ddd eee fff/;
$c->visit('/foo/bar/baz', \@captures, \@arguments);
$c->go('/foo/bar/baz', \@captures, \@arguments);
@capturesと@arguments引数は、それぞれ呼び出し先からは$c->request->captures、$c->request->args経由でアクセスできます。
なお、ドキュメントでは\@captures、\@argumentsの順番になっていますが、筆者が確認したところでは、この逆で指定する必要がありました。
(2)コントローラのクラス、メソッド名を指定
メソッド名を省略してクラス名だけを指定する場合には、visitやgoメソッドではコントローラだけを指定できます。この場合、コントローラクラスにはprocess()メソッドを定義しておく必要があります。
また、クラス、メソッド名を指定する呼び出しの場合でも、アクション名を指定した場合と同様に、2種類の引数を配列として渡すことができます。
