コミュニティーっぽいサービスで、 User has many Microposts *1 のような関係が設立する場合のルーティングを resource を用いてよしなに作る tips をまとめてみました。
Nested Resource
Resrouce を利用すれば基本的なルーティングを作成してくれますが、 ActiveRecord Model をネストした構造のルーティングを設定してみましょう。
resources :users do resources :microposts end
作成されるルーティングは下記のようになります。
URI Pattern Controller#Action GET /users/:user_id/microposts(.:format) microposts#index POST /users/:user_id/microposts(.:format) microposts#create GET /users/:user_id/microposts/new(.:format) microposts#new GET /users/:user_id/microposts/:id/edit(.:format) microposts#edit GET /users/:user_id/microposts/:id(.:format) microposts#show PATCH /users/:user_id/microposts/:id(.:format) microposts#update PUT /users/:user_id/microposts/:id(.:format) microposts#update DELETE /users/:user_id/microposts/:id(.:format) microposts#destroy
Shallow で microposts 単体の URL を定義する
前述の Nested Resource の場合、microposts 単体の perma-link を用意しようとすると /users/:user_id/microposts/:id となり冗長であるため shallow を指定することによって
resources :users, shallow: true do resources :microposts end
作成される routing は下記のように変化して、micropost 単体の Permalink とよしなに解釈するアクションと、リレーション上必ず :user_id が必要なアクションはネストされるように解釈してくれます。
URI Pattern Controller#Action GET /users/:user_id/microposts(.:format) microposts#index POST /users/:user_id/microposts(.:format) microposts#create GET /users/:user_id/microposts/new(.:format) microposts#new GET /microposts/:id/edit(.:format) microposts#edit GET /microposts/:id(.:format) microposts#show PATCH /microposts/:id(.:format) microposts#update PUT /microposts/:id(.:format) microposts#update DELETE /microposts/:id(.:format) microposts#destroy
Member
ネストされたアクションから User の :id を取り扱うためには :user_id として参照していましたが、さらに Member を指定することによって
resources :users, shallow: true do member do resources :microposts end end
ルーティングは下記のようになり、:user_id を :id として取り扱うことができます。User の :id がわかれば、その User が所有する microposts は自明である場合などは、より自然に取り扱うことができるでしょう。
URI Pattern Controller#Action GET /users/:id/microposts(.:format) microposts#index POST /users/:id/microposts(.:format) microposts#create GET /users/:id/microposts/new(.:format) microposts#new
Collection
User :id にひもづく当該 User の「プロフィールもっとみる画面」を作る場合と、そもそも「新着のユーザー一覧」を出したい場合などの使い分けをするには
たとえば下記のように collection を指定してみると
resources :users, shallow: true do member do resources :microposts get 'profile_more' #当該ユーザのプロフィールをもっとみる画面を出したい end collection do get 'new_users' #そもそも新着のユーザー一覧を出したい end end
「プロフィールもっとみる」(profile_more)は :id あり、「新着ユーザー一覧」は :user_id 無しのルーティングとなります。今回設定してみた /users/:id/profile_more のルーティングをみると、前述の Member のありがたみというのも同時にわかりますね。
profile_more_user GET /users/:id/profile_more(.:format) users#profile_more new_users_users GET /users/new_users(.:format) users#new_users
*1:Tutorial で作る model をそのままつかっています http://ruby.railstutorial.org/chapters/a-demo-app#sec-demo_user_has_many_microposts