RailsでDB操作をするときに、必要なルーティングをまとめて生成してくれるresourcesという記述方法があります。
resourcesを使うと、シンプルな記述でページの表示から、新規登録、編集、削除まで8個のアクションに対するルーティングを一度に登録するこごができます。
ただし、時にはその決められた8つのアクション以外を追加で登録したい場合もあります。
ここでは、resourcesに独自のルーティングを追加するための、member(メンバー)とcollection(コレクション)の使い方と違いについて解説しています。
なお、resourcesで追加されるのは次の8つです。
アクション | HTTP動詞 | パス | 内容 |
---|---|---|---|
index | GET | /コントローラ名 | 一覧を表示 |
create | POST | /コントローラ名 | データ追加処理 |
new | GET | /コントローラ名/new | データ追加用の画面 |
edit | GET | /コントローラ名/:id/edit | 指定したデータを変更する画面 |
show | GET | /コントローラ名/:id | 指定したデータの詳細画面 |
update | PATCH | /コントローラ名/:id | 指定したデータの更新処理(変更箇所のみ) |
update | PUT | /コントローラ名/:id | 指定したデータの更新処理(全体を更新) |
destroy | DELETE | /コントローラ名/:id | 指定したデータの削除処理 |
ルーティングのmemberとcollectionとは?
ルーティングの中で設定する、member(メンバー)とcollectoin(コレクション)とは、resourcesで生成されるルートに、決められたルート以外のルートを追加するための処理です。
resourcesのブロック(doとend)の中で使います。
memberとcollectionの違い
member(メンバー)とcollectoin(コレクション)の違いは、ルートを生成したときに:id
をつけるかどうかの違いです。
処理 | 内容 | 生成されるルートの例 |
---|---|---|
member | :idがつくURIを生成する | /users/:id/info |
collection | :idがつかないURIを生成する | /users/contact |
collectionとは集めるといった集合体の意味なので、全体に共通したデータを扱うためのルートになります。
memberは集団の中の一人の意味なので、個別のデータを扱うためのルートになります。
:idがつくかどうかの違いとは?
resourcesを使うと次のように2パターンのURLが生成されます。
- 個々のデータに紐づかない(一覧、新規登録)
- 個々のデータに紐づく(詳細、編集、削除)
個々のデータに紐づけるためには、データ毎に固有のidを、URIに:idとして含めます。
個々のデータに紐づかない(一覧、新気登録)
個々のデータに紐づける必要がない、一覧(index)や新規登録(new)のURLには、:idがつきません。
- indexアクションののURI例: /users
- newアクションののURI例: /users/new
個々のデータに紐づく(詳細、編集、削除)
一方、個々のデータに紐づく、詳細(show)、編集(edit)、削除(destroy)のURLには、:idがつきます。
- showアクションののURI例: /users/:id
- editアクションののURI例: /users/:id/edit
それぞれのパターンにマッチしたルートを区別して生成するために、memberとcollectionで区別しています。
collectionの使い方
:idなしのパスを生み出すcollectionでルートを指定する方法は3つあります。
- パスとアクションが一致する場合
- パスとアクションが一致しない場合
- on: :collectionを使う
パスとアクションが一致する場合
/users/contactにアクセスして、contactアクションを実行する場合など、URIとアクション名が一致する場合は以下のように書きます。
resources :コントローラ名 do
collection do
メソッド名 :アクション名
end
end
シンボルではなく、文字列で指定しても同じ処理になります。
resources :コントローラ名 do
collection do
メソッド名 'アクション名'
end
end
パスとアクションが一致しない場合
パスとアクションが一致しない場合は、actionオプションを使ってactionを指定します。
resources :コントローラ名 do
collection do
メソッド名 :パス, action: :アクション名
end
end
シンボルではなく、文字列で指定しても同じ処理になります。
resources :コントローラ名 do
collection do
メソッド名 'パス', action: 'アクション名'
end
end
on: :collectoinを使う
collection do ~ end
の処理は、 on: :collectoin
を使った処理に置き換えることができます。
resources :コントローラ名 do
メソッド名 :アクション名, on: :collection
メソッド名 :パス, action: :アクション名, on: :collection
end
collectoin(コレクション)の実例
メソッドやアクション指定の有無、シンボルと文字列の指定をした以下のようなルーティングで、生成されるルートの実例です。
collection do ~ endを使った場合
Rails.application.routes.draw do
resources :users do
collection do
get :search1
post 'search2'
#アクションを個別に指定する場合
get :contact1, action: :action1
post :contact2, action: 'action2'
put 'contact3', action: 'action3'
delete 'contact4', action: :action4
end
end
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern Controller#Action
search1_users GET /users/search1(.:format) users#search1
search2_users POST /users/search2(.:format) users#search2
contact1_users GET /users/contact1(.:format) users#action1
contact2_users POST /users/contact2(.:format) users#action2
contact3_users PUT /users/contact3(.:format) users#action3
contact4_users DELETE /users/contact4(.:format) users#action4
on: :collectoinを使った場合
Rails.application.routes.draw do
resources :users do
get :search1, on: :collection
post 'search2', on: :collection
#アクションを個別に指定する場合
get :contact1, action: :action1, on: :collection
post :contact2, action: 'action2', on: :collection
put 'contact3', action: 'action3', on: :collection
delete 'contact4', action: :action4, on: :collection
end
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern Controller#Action
search1_users GET /users/search1(.:format) users#search1
search2_users POST /users/search2(.:format) users#search2
contact1_users GET /users/contact1(.:format) users#action1
contact2_users POST /users/contact2(.:format) users#action2
contact3_users PUT /users/contact3(.:format) users#action3
contact4_users DELETE /users/contact4(.:format) users#action4
memberの使い方
memberの使い方はcollectionと同じです。(上記のcollectionをmemberに変えるだけです)
:idつきのパスを生み出すmemberでルートを指定する方法は2つあります。
- パスとアクションが一致する場合
- パスとアクションが一致しない場合
- on: :memberを使う
パスとアクションが一致する場合
/users/:id/loginにアクセスして、loginアクションを実行する場合など、URIとアクション名が一致する場合は以下のように書きます。
resources :コントローラ名 do
member do
メソッド名 :アクション名
end
end
シンボルではなく、文字列で指定しても同じ処理になります。
resources :コントローラ名 do
member do
メソッド名 'アクション名'
end
end
パスとアクションが一致しない場合
パスとアクションが一致しない場合は、actionオプションを使ってactionを指定します。
resources :コントローラ名 do
member do
メソッド名 :パス, action: :アクション名
end
end
シンボルではなく、文字列で指定しても同じ処理になります。
resources :コントローラ名 do
member do
メソッド名 'パス', action: 'アクション名'
end
end
on: :memberを使う
member do ~ end
の処理は、 on: :member
を使った処理に置き換えることができます。
resources :コントローラ名 do
メソッド名 :アクション名, on: :member
メソッド名 :パス, action: :アクション名, on: :member
end
member(メンバー)の実例
メソッドやアクション指定の有無、シンボルと文字列の指定をした以下のようなルーティングで、生成されるルートの実例です。
member do ~ endを使った場合
Rails.application.routes.draw do
resources :users do
member do
get :login1
post 'login2'
get :info1, action: :action1
post :info2, action: 'action2'
put 'info3', action: 'action3'
delete 'info4', action: :action4
end
end
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern Controller#Action
login1_user GET /users/:id/login1(.:format) users#login1
login2_user POST /users/:id/login2(.:format) users#login2
info1_user GET /users/:id/info1(.:format) users#action1
info2_user POST /users/:id/info2(.:format) users#action2
info3_user PUT /users/:id/info3(.:format) users#action3
info4_user DELETE /users/:id/info4(.:format) users#action4
on: :memberを使った場合
Rails.application.routes.draw do
resources :users do
get :login1, on: :member
post 'login2', on: :member
get :info1, action: :action1, on: :member
post :info2, action: 'action2', on: :member
put 'info3', action: 'action3', on: :member
delete 'info4', action: :action4, on: :member
end
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern Controller#Action
login1_user GET /users/:id/login1(.:format) users#login1
login2_user POST /users/:id/login2(.:format) users#login2
info1_user GET /users/:id/info1(.:format) users#action1
info2_user POST /users/:id/info2(.:format) users#action2
info3_user PUT /users/:id/info3(.:format) users#action3
info4_user DELETE /users/:id/info4(.:format) users#action4
memberとgetの違い
通常のルートを指定するgetをresourcesにネストさせると、memberと似たように個別のデータを表すパラメータがつきます。(on: :memberを付けない場合)
memberとgetの違いは、生成されるルートのURIにつくパラメータ名やprefixが異なることです。
対象 | Prefix | Verb | URI Pattern | Controller#Action |
---|---|---|---|---|
差異 | 違う | 同じ | 違う | 同じ |
memberでないget | モデル名_アクション名 | GET | /コントローラ名/:モデル名_id/アクション名 | コントローラ名#アクション名 |
member | アクション名_モデル名 | GET | /コントローラ名/:id/アクション名 | コントローラ名#アクション名 |
resourcesにgetのネストで生成されるルート
resourcesの中にgetを記述して、ネストさせた場合に生成されるルートは次のようになります。
resources :users do
get :info
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern Controller#Action
user_info GET /users/:user_id/info(.:format) users#info
URIのパラメータが :idではなく、:user_idになっています。また、Prefixはuserが前方に来ています。
memberとgetの違い実例
resourcesの中に通常のgetとmemberとしてのgetをそれぞれ記述すると違いがわかりやすいです。
resources :users do
get :info1
get :info2, on: :member
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern Controller#Action
user_info1 GET /users/:user_id/info1(.:format) users#info1
info2_user GET /users/:id/info2(.:format) users#info2
resourcesの中にmemberでないgetを指定しても使えないことはありませんが、resourcesで生成された他のルートと規則性が異なるのでお勧めはできません。
memberとcollectionを同時に使う
もちろん、resourcesの中で、memberとcollectionまた、それ以外のルートも同時に指定することができます。
Rails.application.routes.draw do
resources :users do
get :info1
get :info2, on: :member
member do
get :login1
post 'login2'
end
collection do
get :search1
post 'search2'
end
resources :projects
end
end
↓ 生成されるルート
# rails routes
Prefix Verb URI Pattern
Controller#Action
users#info1
info2_user GET /users/:id/info2(.:format)
users#info2
login1_user GET /users/:id/login1(.:format)
users#login1
login2_user POST /users/:id/login2(.:format)
users#login2
search1_users GET /users/search1(.:format)
users#search1
search2_users POST /users/search2(.:format)
users#search2
user_projects GET /users/:user_id/projects(.:format)
projects#index
POST /users/:user_id/projects(.:format)
projects#create
new_user_project GET /users/:user_id/projects/new(.:format)
projects#new
edit_user_project GET /users/:user_id/projects/:id/edit(.:format)
projects#edit
user_project GET /users/:user_id/projects/:id(.:format)
projects#show
PATCH /users/:user_id/projects/:id(.:format)
projects#update
PUT /users/:user_id/projects/:id(.:format)
projects#update
DELETE /users/:user_id/projects/:id(.:format)
projects#destroy