QA@IT

routes.rbの「match ':controller(/:action(/:id))(.:format)'」はなぜ使わない方が良いのでしょうか?

3357 PV

Railsのroutes.rbの「match ':controller(/:action(/:id))(.:format)'」というルーティングの設定方法は非推奨とされているかと思います。

config/routes.rb

  # This is a legacy wild controller route that's not recommended for RESTful applications.
  # Note: This route will make all actions in every controller accessible via GET requests.
  # match ':controller(/:action(/:id))(.:format)'

しかし、少し大きめのWebアプリケーションや、複雑なページ遷移を必要とするWebアプリケーションなどでは、routes.rbの記述が複雑になってしまったり、優先順位の関係で、予期せぬ動作不良を起こしてしまうような場合もあるのではないかと思っています。

そのため、単純な開発効率や、ルーティングの分かり易さ、共同開発者内での認識統一の図りやすさ、などの点では「match ':controller(/:action(/:id))(.:format)'」この一行の設定だけ書いておけば、全てのルーティングを一つのルールで理解できるため、分かり易く、事故も起き難いのではないか、というような気もしています。(ルーティングの設定に掛ける時間も短縮でき、その分、本質的なアプリケーションの開発に割ける時間に充当できるとも考えられます。)

非推奨とする理由としては、全てのルーティングにGETアクセス出来てしまう、RESTful設計に準拠すべき、Railsの流れに従うべき、などの理由があるのかと思いますが、上記に挙げた利点なども鑑み、それでもコスト対効果で効果の方が上回る、もしくは使うべきでは無い絶対的理由などはあるのでしょうか?

回答

具体的な「非推奨」の理由の1つは既に labocho さんが回答なさっていますので、別の観点から説明してみます。

まず前提として、2.x以降のRailsは「Web経由で色々なリソースを提供することでアプリケーションの機能を実現する」ためのフレームワークになりました。ですから、レールから降りずにRailsアプリを作る場合は、「このアプリケーションが提供するリソースはどんなものか」を考えるのがとてもとても肝要です。

ユーザや企画サイドから、画面イメージや画面遷移図でやってくる「要望」をそのままルーティングやアクションにひもづけるのではなく、まずはどういうリソースを操作したいのかという観点で考えなおすのがレールに乗るコツです。

で、その考えた結果を書いておくのが config/routes.rb なわけです。

そのため、単純な開発効率や、ルーティングの分かり易さ、共同開発者内での認識統一の図りやすさ、などの点では「match ':controller(/:action(/:id))(.:format)'」この一行の設定だけ書いておけば、全てのルーティングを一つのルールで理解できるため、分かり易く、事故も起き難いのではないか、というような気もしています。

これは慣れの問題かなと思いますが、私なんかはresourcesが書いてあると「ああこのアプリはこういうリソースを提供してるのね。only: とかついてるあたり、このリソースは読み取り専用なのね」と読めるのはとても嬉しいです。全体を概観しやすく『ルーティングの分かり易さ、共同開発者内での認識統一の図りやすさ』が向上します。

ということで、

(ルーティングの設定に掛ける時間も短縮でき、その分、本質的なアプリケーションの開発に割ける時間に充当できるとも考えられます。)

ルーティングというか、アプリケーションはどんなリソースを提供するか、というのを考えるはまさに『本質的なアプリケーション開発』ではないでしょうか。

慣れや考え方の問題ではあるので、どうしても:controller/:action/:idを使うのを止めることはできませんが、Railsを使う以上はresourcesをうまく使いこなす方向に慣れたほうがよいと思います。

とはいえ、この回答はやや抽象的にすぎますね。レールに乗った場合の現世利益は http://qa.atmarkit.co.jp/q/2092#answer_14495 にも書いていますので、よろしければご覧ください。

編集 履歴 (0)
  • ありがとうございます。とても参考になります。やはりroutes.rbをルーティングの設定というよりは、リソースの一覧を書く場所、のように考えた方が納得しやすそうですね。 -

一番の問題は、ご自身も挙げていらっしゃいますが、すべてのアクションが GET で実行されてしまう、という点だと思います。

HTTP の仕様では GET リクエストは副作用がないことになっているため、リソースの変更を伴うアクションを GET で実行できてしまうのは問題があります。

たとえば、Rails では CSRF 対策として、リソースの変更を伴うリクエストにはトークンを必要としますが、GET リクエストではこれを必要としないため、CSRF に対する脆弱性が生まれます (twitter で短縮 URL をクリックしたら http://example.com/users/1/destroy でユーザ削除されちゃった、とか)。

意図的な攻撃でなくともユーザが URL を誰かに知らせたり、クローラや prefetch を行うブラウザ拡張機能などにより意図しないリソースの変更が起こりえます。

ほかには Controller クラスの public なメソッドが外部から実行し放題、というのも、無用にセキュリティ上のリスクを高めてしまうように思います。

編集 履歴 (0)
  • ありがとうございます。GETアクセスによる副作用、セキュリティリスクの向上などが特に問題になる、という事ですね。参考になります。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。