またはまった。default アクションでの args の扱い
sub default : Private { my ( $self, $c ) = @_; shift @{ $c->req->args }; ... }
というmizzyさんのhackを施して過ごして来ましたが、アクションの階層を深くした時に意図しない結果になってしまいました。
Controller::Fooアクションで/foo/1にアクセスした時、defaultアクションにおけるargsは['foo', '1']となるのでshiftすればいいのですが、
Controller::Foo::Barアクションで/foo/bar/1にアクセスした時、defaultアクションにおけるargsは['foo', 'bar', '1']となるのでshift一回では足りません。
この場合、$c->namespaceに'foo/bar'と入っているので'/'の数に合わせてshiftするように修正してみました。
sub default : Private { my ( $self, $c ) = @_; for ( 0 .. $c->namespace =~ tr{/}{} ) { shift @{ $c->req->args }; }
たっぷり罠が潜んでいそうです。
こんなことしなくても良いのです。 Catalyst::Manual::Introの 「Actions」→「Action types」→「Built-in Private Actions」→「default : Private」に 「これが嫌ならPathを使え」と載っています。package MyApp::Controller::Foo::Bar; sub default : Private { my ( $self, $c ) = @_; $c->res->body(join q{, }, @{ $c->req->args }); }
- URI:http://localhost:3000/foo/bar/1
- 結果:foo, bar, 1
package MyApp::Controller::Foo::Bar; sub default : Path { my ( $self, $c ) = @_; $c->res->body(join q{, }, @{ $c->req->args }); }
- URI:http://localhost:3000/foo/bar/1
- 結果:1