【Rails】resourcesにルートを追加する方法|routes.rbのmember(メンバー)とcollection(コレクション)とは?違いと使い方を徹底解説

rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。

RailsでDB操作をするときに、必要なルーティングをまとめて生成してくれるresourcesという記述方法があります。

resourcesを使うと、シンプルな記述でページの表示から、新規登録、編集、削除まで8個のアクションに対するルーティングを一度に登録するこごができます。

ただし、時にはその決められた8つのアクション以外を追加で登録したい場合もあります。

ここでは、resourcesに独自のルーティングを追加するための、member(メンバー)とcollection(コレクション)の使い方と違いについて解説しています。

なお、resourcesで追加されるのは次の8つです。

アクションHTTP動詞パス内容
indexGET/コントローラ名一覧を表示
createPOST/コントローラ名データ追加処理
newGET /コントローラ名/newデータ追加用の画面
editGET/コントローラ名/:id/edit指定したデータを変更する画面
showGET/コントローラ名/:id指定したデータの詳細画面
updatePATCH/コントローラ名/:id指定したデータの更新処理(変更箇所のみ)
updatePUT/コントローラ名/:id指定したデータの更新処理(全体を更新)
destroyDELETE/コントローラ名/: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が生成されます。

  1. 個々のデータに紐づかない(一覧、新規登録)
  2. 個々のデータに紐づく(詳細、編集、削除)

個々のデータに紐づけるためには、データ毎に固有の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つあります。

  1. パスとアクションが一致する場合
  2. パスとアクションが一致しない場合
  3. on: :collectionを使う

パスとアクションが一致する場合

/users/contactにアクセスして、contactアクションを実行する場合など、URIとアクション名が一致する場合は以下のように書きます。

  resources :コントローラ名 do
    collection do
      メソッド名 :アクション名
    end
  end

シンボルではなく、文字列で指定しても同じ処理になります。

  resources :コントローラ名 do
    collection do
      メソッド名 'アクション名'
    end
  end
注意点

すべて小文字で指定します。メソッド名を大文字で記述するとエラーになります。

〇 get
× GET


パスとアクションが一致しない場合

パスとアクションが一致しない場合は、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つあります。

  1. パスとアクションが一致する場合
  2. パスとアクションが一致しない場合
  3. on: :memberを使う

パスとアクションが一致する場合

/users/:id/loginにアクセスして、loginアクションを実行する場合など、URIとアクション名が一致する場合は以下のように書きます。

  resources :コントローラ名 do
    member do
      メソッド名 :アクション名
    end
  end

シンボルではなく、文字列で指定しても同じ処理になります。

  resources :コントローラ名 do
    member do
      メソッド名 'アクション名'
    end
  end
注意点

すべて小文字で指定します。メソッド名を大文字で記述するとエラーになります。

〇 get
× GET


パスとアクションが一致しない場合

パスとアクションが一致しない場合は、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が異なることです。

対象PrefixVerbURI PatternController#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


参考リンク



タイトルとURLをコピーしました