スポンサーリンク
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(単発)を先に書くようにするべき。

 
 
 
 