だるろぐ

だるいぶろぐです

Pickles::Dispatcher::Auto というモジュールを書いた

https://github.com/hirafoo/p5-Pickles-Dispatcher-Auto


Pickles というwafがあって、これの dispatcher はルーティングを記述したファイルが必須で、コントローラに定義されたアクションはこれに書かないといけない。
コントローラに100個アクションがある場合とか面倒なので、自動でディスパッチしてほしいなあと思ったのでそーいうのを書いた。

Picklesの中身

ディスパッチを自動化するにはオリジナルの Pickles::Dispatcher だけいじればいいんだろーと思うとそうではない。
見る順番としては

  1. myapp.psgi
  2. Pickles::WebApp
  3. Pickles::Context
  4. Pickles::Dispatcher

となる。


ディスパッチがハンドラとコンテキストに関係してるので、ディスパッチャだけ上書きすればいいわけではない。
なのでモジュールの中で Pickles::Context の _prepare / controller_class のメソッドを上書きしている。

悩みどころ

/hoge

という path_info を処理するコントローラ・アクションとテンプレートはそれぞれ

  • MyApp::Controller::Root#hoge
  • /hoge.html

でいいと思う。これは不自然ではなく、反論も無いと思う。

めんどいのはこんな 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 を使った時に、

  1. Pickles::WebApp
  2. Pickles::Context
  3. Pickles::Dispatcher
  4. 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 の領域ですよ」と扱うか、「ここ以下はコントローラですよ」と扱うかの差なので、やりたい事や実装にもよるか。