どうも、お久しぶりの vkgtaro です。自分の blog に書こうかと思ったんだけど、購読者数が多いこちらに書くよ!
JPA の活動とか charsbar さんの連載で Catalyst が盛り上がってきてますね。と言うことで、Catalyst::Controller::Resources を紹介したいと思います。(JPA のセミナーでは Action::REST が紹介されてたようだけど、個人的には Resources が好きです。Resources 使うために Catalyst 使ってると言っても過言じゃないくらい。)
Resources を使うと HTTP method の GET / POST / PUT / DELETE に応じた Chained がカンタンに作れます。Ruby on Rails をやったことある人だと map.resources と言えばわかるのかな? 僕は rails やったことがないのでわからないんですけれども。
使い方はこんな風に Catalyst::Controller の代わりに Catalyst::Controller::Resources を使うだけ。
package Jnsn::Controller::Articles; use strict; use warnings; use parent 'Catalyst::Controller::Resources';
これで、以下のような URI / method と action のマップができる。
| /articles | get | Articles#list |
| /articles/new | get | Articles#post |
| /articles | post | Articles#create |
| /articles/{article_id} | get | Articles#show |
| /articles/{article_id}/edit | get | Articles#edit |
| /articles/{article_id} | put | Articles#update |
| /articles/{article_id} | delete | Articles#destroy |
これは、対応する action を作らなければ実際にはチェーンされません。
なので必要ない URI は作りたくないという人も安心です。
ちなみに {article_id} は、3番めの引数として渡ってくるよ。
# PUT /articles/{article_id} sub update { my ($self, $c, $article_id) = @_; }
この id を特定して何かの操作をするものを member, そうじゃないやつを collection と REST では言うみたいですね。(内部的には member と colllection に chain してるのは起動時のデバッグログでわかりますね。)
Resources の魅力はまだあります。articles に属している comments を作りたいなぁ、URI は /articles/{article_id}/comments/{comment_id} みたくしたいなぁ、と思ったら Comments コントローラ内でこうすればいいです。
package Jnsn::Controller::Articles::Comments; use strict; use warnings; use parent 'Catalyst::Controller::Resources'; __PACKAGE__->config( belongs_to => 'Articles', );
こうすることによって Articles::Comments は Catalyst のチェーン的に Articles に属します。
| /articles/{article_id}/comments | get | Articles::Comments#list |
| /articles/{article_id}/comments/new | get | Articles::Comments#post |
| /articles/{article_id}/comments | post | Articles::Comments#create |
| /articles/{article_id}/comments/{comment_id} | get | Articles::Comments#show |
| /articles/{article_id}/comments/{comment_id}/edit | get | Articles::Comments#edit |
| /articles/{article_id}/comments/{comment_id} | put | Articles::Comments#update |
| /articles/{article_id}/comments/{comment_id} | delete | Articles::Comments#destroy |
さらに、マップにない action を追加したいなぁと思ったら、config で追加しましょう。
article 追加時の確認画面と編集時の確認画面を追加してみます。
# Jnsn::Controller::Articles; __PACKAGE__->config( collection => { confirm => 'post', }, member => { confirm_edit => 'post', } ); # POST /articles/confirm sub confirm { my ($self, $c) = @_; } # POST /articles/{article_id}/confirm_edit sub confirm_edit { my ($self, $c, $article_id) = @_; }
ね、カンタンでしょう?
ブラウザーから PUT と DELETE 送れない問題は Catalyst::Request::REST::ForBrowser を使うとうまくできるよ。
(参考:Catalyst::Controller::Resources でオーバーロード POST を使いたい - Yet Another Hackadelic)
なお、この記事は Catalyst 5.80004, Catalyst::Controller::Resources 0.07 で書いてます。Cat 5.7 系で Resources 使うときは 0.04 を使うといいですよ!



Leave a comment