無駄に深いネスト
元記事はこちら
翻訳
Bad Smell
map.resources :posts do |post| post.resources :comments do |comment| comment.resources :favorites end end <%= link_to post_comment_favorite_path(@post, @comment, @favorite) %>
3階層にネストしたルーティングは本当に必要でしょうか?ルーティングをネストするということは、子階層のリソースが親階層のリソースに依存しているということを意味します。 上記の例では、commentsというリソースがpostに依存しているということです。 しかし、favoritesはcommentに依存するものですから、favoritesのリソースがpostに依存している必要は全くありません。
Refactor
map.resources :post do |post| post.resources :comments end map.resources :comments do |comment| comment.resources :favorites end <%= link_to comment_favorite_path(@comment, @favorite) %>
以上の理由から、3階層のネストを2階層に減らしたルーティングにリファクタリングしました。favoritesへのurlもこうすることで短くなります。
Updated by @flyerhzm
無駄に深いネストを回避する新しい方法です。
Refactor 2
map.resources :posts, :shallow => true do |post| post.resources :comments do |comment| comment.resources :favorites end end <%= link_to comment_favorite_path(@comment, @favorite) %>
見ての通り、shallow => true
オプションをpostのルーティングに追加することで、1階層か2階層以内に抑えてルーティングを生成します。
以下のように生成されます。
posts GET /posts(.:format) {:action=>"index", :controller=>"posts"} POST /posts(.:format) {:action=>"create", :controller=>"posts"} new_post GET /posts/new(.:format) {:action=>"new", :controller=>"posts"} edit_post GET /posts/:id/edit(.:format) {:action=>"edit", :controller=>"posts"} post GET /posts/:id(.:format) {:action=>"show", :controller=>"posts"} PUT /posts/:id(.:format) {:action=>"update", :controller=>"posts"} DELETE /posts/:id(.:format) {:action=>"destroy", :controller=>"posts"} post_comments GET /posts/:post_id/comments(.:format) {:action=>"index", :controller=>"comments"} POST /posts/:post_id/comments(.:format) {:action=>"create", :controller=>"comments"} new_post_comment GET /posts/:post_id/comments/new(.:format) {:action=>"new", :controller=>"comments"} edit_comment GET /comments/:id/edit(.:format) {:action=>"edit", :controller=>"comments"} comment GET /comments/:id(.:format) {:action=>"show", :controller=>"comments"} PUT /comments/:id(.:format) {:action=>"update", :controller=>"comments"} DELETE /comments/:id(.:format) {:action=>"destroy", :controller=>"comments"} comment_favorites GET /comments/:comment_id/favorites(.:format) {:action=>"index", :controller=>"favorites"} POST /comments/:comment_id/favorites(.:format) {:action=>"create", :controller=>"favorites"} new_comment_favorite GET /comments/:comment_id/favorites/new(.:format) {:action=>"new", :controller=>"favorites"} edit_favorite GET /favorites/:id/edit(.:format) {:action=>"edit", :controller=>"favorites"} favorite GET /favorites/:id(.:format) {:action=>"show", :controller=>"favorites"} PUT /favorites/:id(.:format) {:action=>"update", :controller=>"favorites"} DELETE /favorites/:id(.:format) {:action=>"destroy", :controller=>"favorites"}
:shallowは良い解決策だと思います。このオプションにより、以下のような使い方ができます。
post_comment_path(1, 1) comment_path(1) comment_favorite_path(1, 1) favorite_path(1)
素晴らしい!でもrailsドキュメントに載っていないのが残念です。
感想
railsドキュメントに載っていない 掲載されるようになったみたい。 ActionDispatch::Routing::Mapper::Resources
これも読んで、できる限りRESTfulなルーティングに近づけるようにしていると、1アクションの責務がとても明確になって良い。 postd.cc