Mojoliciousのルーティングでactionに`send`や`finish`が使えない

結論から

言うと、ルーティングオブジェクトはMojolicious::Controllerを承継しているため、そのメソッドはactionに指定できないのでsendやfinishは使えないってことのようです。

解説

まず、通常よくあるディスパッチャ(ルーティングしてる部分)を見てみましょう。

my $r = $self->routes;
$r->any('/contact/')->to('contact#index');         # 入力画面
$r->post('/contact/check/')->to('contact#check');  # 確認画面
$r->post('/contact/send/')->to('contact#send');    # 送信処理?
$r->get('/contact/finish/')->to('contact#finish'); # 完了画面?

この例では、お問合せフォームのそれぞれのアクションが実行され、それぞれの画面が表示されるはずです。 ちなみにto('contact#index')to(controller=>'contact', action=>'index')と同じ意味になります。半角シャープ(#)区切りでコントローラーとその中のアクション(実態はpmファイルとその中の関数です)を指します。

ところが、実際に上記のルーティングで実行させ、/contact/send/にアクセスすると、Mojoliciousのエラー画面が表示されてしまいます。


Page not found... yet!
None of these routes could generate a response for your GET request for /send/, maybe you need to add a new one? 

GETリクエストに対する/send/のルーティングが無いよ、書くの忘れてない? っていうエラーメッセージなんですが、見当はずれなので無視です。それよりデバッグログの方をよく見ると、こんなログが残っています。


[debug] Action "send" is not allowed.

"send"アクションは許可されていませんっていうエラーです。そうなんです、sendはアクションに許可されないんです。

なんで?

アクション先で指定したオブジェクト(pmファイル)もMojolicious::Controllerを承継しているので、Mojolicious::Controllerのメソッド一覧に既にあるsendメソッドと衝突してしまったのです。同じ理由でfinishも使えませんです。

メソッド一覧を見てると、他にも結構ぶつかりそうな名称のメソッドがありますね・・。

よくあるフォーム遷移のアクション名付け

ということで、以下、私がよく使うエラーにならないアクションの名づけ方です。ご参考まで。

my $r = $self->routes;
$r->any('/contact/')->to('contact#index');          # 入力画面
$r->post('/contact/check/')->to('contact#check');   # 確認画面
$r->post('/contact/submit/')->to('contact#submit'); # 送信処理
$r->get('/contact/done/')->to('contact#done');      # 完了画面

確認したバージョン

  • Mojolicious 4.76
  • Perl 5.16.2(darwin)