スポンサーリンク
resourcesとresource
Railsで何らかのリソースに対するCRUD処理を行うためのルーティングを手っ取り早く生成する方法に、resourcesメソッドとresourceメソッドがある。
これらの違いについてメモっておく。
スポンサーリンク
resourcesとは
resourcesは、複数のリソースに対するCRUD処理を行うためのルーティングを生成する。
例えば、複数の本(books)についてのCRUD処理を行う為のルーティングを生成するにはroutes.rbにおいて、
1 2 3 4 | Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html resources :books end |
※リソース名がbooksと複数形になっていることにも注意
とやるだけで、以下のルーティングが生成される。
1 2 3 4 5 6 7 8 9 | Prefix Verb URI Pattern Controller#Action books GET /books(.:format) books#index POST /books(.:format) books#create new_book GET /books/new(.:format) books#new edit_book GET /books/:id/edit(.:format) books#edit book GET /books/:id(.:format) books#show PATCH /books/:id(.:format) books#update PUT /books/:id(.:format) books#update DELETE /books/:id(.:format) books#destroy |
urlに:idを含むことで、それぞれのリソース(book)ごとにCRUD処理を行うことができる。
リソースが複数なので、/booksに対するGETリクエストが返すのはリソースの一覧画面(indexアクション)であることが分かる。
resourceとは
resourceは、ただ1つのリソースに対するCRUD処理を行うためのルーティングを生成する。
例えば、一冊の本(book)についてのCRUD処理を行うためのルーティングを生成するには、routes.rbにおいて、
1 2 3 4 | Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html resource :book end |
※リソース名がbookと単数形になっていることにも注意
とやるだけで、以下のルーティングが生成される。
1 2 3 4 5 6 7 8 | Prefix Verb URI Pattern Controller#Action new_book GET /book/new(.:format) books#new edit_book GET /book/edit(.:format) books#edit book GET /book(.:format) books#show PATCH /book(.:format) books#update PUT /book(.:format) books#update DELETE /book(.:format) books#destroy POST /book(.:format) books#create |
こちらの場合は、リソースは1つだけなのでurlに:idを含む必要がない。そして、一覧画面(indexアクション)が必要ないので、/bookに対するGETリクエストはそのリソースの表示(showアクション)であることが分かる。
resourcesとresourceを組み合わせて使う
たった1つのリソースについてのCRUD処理というのは、実際はそんなに使い所がないと思われる。
が、resourcesとresourceを組み合わすことで、以下のようなルーティングを簡単に作ることができる。
- 全user一覧表示
- 各user詳細表示
- 自user詳細表示
- 自user登録フォーム表示
- 自user登録処理
- 自user編集フォーム表示
- 自user編集処理
- 自user削除処理
いわゆる会員サイトのようなものを思い浮かべると分かりやすいと思う。全user一覧、及び各user詳細については誰でも見れるが、user情報の編集などはもちろん自分のものしか出来ない。
実際は、自userを特定するにはログイン機能(session管理)が必要になるが、とりあえずそれは横へ置いておくとして、上記のようなルーティングをresourcesとresourceを組み合わせることによって生成することができる。
1 2 3 4 5 6 | Rails.application.routes.draw do resource :user, only: [:new, :create, :edit, :update, :show, :destroy] resources :users, only: [:index, :show] # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end |
1 2 3 4 5 6 7 8 9 10 | Prefix Verb URI Pattern Controller#Action new_user GET /user/new(.:format) users#new 自user登録フォーム表示 edit_user GET /user/edit(.:format) users#edit 自user編集フォーム表示 user GET /user(.:format) users#show 自user詳細表示 PATCH /user(.:format) users#update 自user編集処理 PUT /user(.:format) users#update DELETE /user(.:format) users#destroy 自user削除処理 POST /user(.:format) users#create 自user登録処理 users GET /users(.:format) users#index 全user一覧表示 GET /users/:id(.:format) users#show 各user詳細表示 |
自userは、sessionで特定できさえすれば、リクエストにわざわざ:idを含む必要はないので、自userに関するルーティングはresourceを使っている。
逆に自分以外のuserについての詳細画面を見る場合は、そのuserのIDを指定しなければならないので、resourcesによってリクエストに:idを含むルーティングを生成している。
resource :userとしても、コントローラー名はusersであることに注意。
単発のリソースと複数のリソースを組み合わせることで効率的なコーディングができるように、あえて単発リソース(user)も複数リソース(users)であっても複数形(users_controller)に統合されるようになっているんだと思う。
resourcesとresourceの順番に注意
resourcesメソッドとresourceメソッドを書く順番には注意が必要。
1 2 3 4 5 6 | Rails.application.routes.draw do resources :users, only: [:index, :show] resource :user, only: [:new, :create, :edit, :update, :show, :destroy] # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end |
↑これは先程とは順番が逆で、結果的に以下のルーティングが生成される。
1 2 3 4 5 6 7 8 9 10 | Prefix Verb URI Pattern Controller#Action users GET /users(.:format) users#index user GET /users/:id(.:format) users#show new_user GET /user/new(.:format) users#new edit_user GET /user/edit(.:format) users#edit GET /user(.:format) users#show PATCH /user(.:format) users#update PUT /user(.:format) users#update DELETE /user(.:format) users#destroy POST /user(.:format) users#create |
よく見ると、Prefixのところ、パスを返す為のヘルパーメソッドが変わってしまっている。
user_pathが/users/:idに割り当てられてしまうことで、/userを返すべきヘルパーメソッドが生成されない?
resource(単発)とresources(複数)を組み合わせてルーティングを作る際は、resource(単発)を先に書くようにするべき。