Pickles::Dispatcher::Auto というモジュールを書いた
https://github.com/hirafoo/p5-Pickles-Dispatcher-Auto
Pickles というwafがあって、これの dispatcher はルーティングを記述したファイルが必須で、コントローラに定義されたアクションはこれに書かないといけない。
コントローラに100個アクションがある場合とか面倒なので、自動でディスパッチしてほしいなあと思ったのでそーいうのを書いた。
Picklesの中身
ディスパッチを自動化するにはオリジナルの Pickles::Dispatcher だけいじればいいんだろーと思うとそうではない。
見る順番としては
- myapp.psgi
- Pickles::WebApp
- Pickles::Context
- Pickles::Dispatcher
となる。
ディスパッチがハンドラとコンテキストに関係してるので、ディスパッチャだけ上書きすればいいわけではない。
なのでモジュールの中で Pickles::Context の _prepare / controller_class のメソッドを上書きしている。
悩みどころ
/hoge
という path_info を処理するコントローラ・アクションとテンプレートはそれぞれ
でいいと思う。これは不自然ではなく、反論も無いと思う。
めんどいのはこんな path_info の場合。
/foo/
コントローラ・アクションの考えとしては
- MyApp::Controller::Foo#index
- MyApp::Controller::Foo::Root#index
が挙がる。一方テンプレートは
/foo/index.html
が自然だと思う。
モジュールを作る上でこのコントローラ・アクションをどっちにするか決めないといけない。
悩んだ末、後者にした。理由は
/
を処理するのが
MyApp::Controller::Root#index
なので。
どうでもいいが、ざっと何かを見た感じ、その中では割と適当だった。
Slash.pm とかもあったような気がしたが空目だと信じる。
いわゆる MyApp::Web とかの名前空間
Catalyst(ハードウェアじゃない方の) 全盛期のときに、 MyApp::Controller じゃなくて MyApp::Web::Controller というような名前空間を推奨するような動きがあった。
大賛成なのだが、 Pickles ではそれが大分実現しづらい。
実はこのモジュール、大分前から原型がある。
http://d.hatena.ne.jp/hirafoo/20110119/1295444740
そっちの方は、あるプロダクトで Pickles を使った時に、
- Pickles::WebApp
- Pickles::Context
- Pickles::Dispatcher
- MyApp.psgi
に手を入れて、
- MyApp::Admin::Controller
- MyApp::PC::Controller
- MyApp::Lite::Controller
- MyApp::Mobile::Controller
のような名前空間で使っていたときに作ったもの。なので実はあれ単体では動かなくて、コードを読んで意図を理解して適切な変更を加える必要がある。駄目ですね。
今回はそもそもの Pickles の流儀に従っているし、各クラスのメソッドを上書きすることなくデフォルトのままで使えるようにしてある。
ところで、この名前空間をデフォルトから変更しよう、というやつ、
MyApp::Controller::Foo::Root MyApp::Controller::Bar::Root
というのと、
MyApp::Foo::Controller::Root MyApp::Bar::Controller::Root
というのではどっちがいいのだろう。ケースバイケースかつ人の好みな気はする。
「ここ以下は Foo の領域ですよ」と扱うか、「ここ以下はコントローラですよ」と扱うかの差なので、やりたい事や実装にもよるか。