Railsにおけるmemberとcollection

こんにちは!kossyです!



日経平均株価が久しぶりに24000円台に回復したようです。



ここ数年はだいたい9-11月に回復する傾向がありますね。
2014年には黒田日銀総裁の追加緩和で上昇、
2016年にはトランプさん当選で上昇、
2017年には選挙での与党の圧勝などで上昇、
というような感じですね。

ちなみに下落するのは2月が多いです。






さて、今回はrailsにおいて、7つのアクション以外のアクションをルーティングで定義するときに使う、
memberとcollcectionの使い方について、ブログに残したいと思います。


環境
Ruby 2.5.1
Rails 5.1.6
MacOS





7つのアクションってなに?
memberとcollectionの説明に移る前に、7つのアクションについて解説してみます。

7つのアクションの役割分担はこちらの記事が詳しかったです。
qiita.com


railsでは、ルーティング定義の際に、

config/routes.rb

get 'URL', to: 'コントローラ名#アクション名'

と記述するか、

config/routes.rb

resources : コントローラ名

と記述すると、ルーティングが設定されます。

ここでresourcesでルーティングを定義すると、
index, new, create, show, edit, update(put/patch), destroyの8つのパスが自動的に定義されます。

rails routesで確認してみましょう。

config/routes.rb

resources :products


$ rails routes

products     GET    /products(.:format)          products#index
             POST   /products(.:format)          products#create
new_product  GET    /products/new(.:format)      products#new
edit_product GET    /products/:id/edit(.:format) products#edit
product      GET    /products/:id(.:format)      products#show
             PATCH  /products/:id(.:format)      products#update
             PUT    /products/:id(.:format)      products#update
             DELETE /products/:id(.:format)      products#destroy

上記のようにアクションが生成されました。




他のアクションはどうすんの?

7つのアクションについては自動で生成されるので構いませんが、
それ以外のアクションはどのように定義すればいいのでしょうか。

ここで登場するのが、memberとcollectionです。

memberの使い方
member は特定のデータ(users/:id/likesのように:idが入るアクション)に対するアクションに利用します。

以下のルーティングはmemberを使ったあるユーザーのお気に入り一覧のルーティングです。

resources :users, only: [:likes] do
    member do
      get 'likes'
    end
  end

$ rails routes
likes_user GET /users/:id/likes(.:format) users#likes

これをmemberを使わずに書くと、

get 'users/:id/likes', to: 'users#likes'

$ rails routes
GET /users/:id/likes(.:format) users#likes

となります。これでも問題なく動作するのですが、
prefixが自動で生成されないという事象が発生します。
Railsではprefixを用いたり、各種オプションを用いて可読性の高いコードを書くことがよしとされているので、
便利なオプションやメソッドはガンガン使いましょう。


collectionの使い方
対してcollectionですが、
collectionはユーザー検索や商品検索等、全てのデータを対象とするアクションに利用します。

以下のルーティングはcollectionを使った商品検索のルーティングの例になります。

config/routes.rb

resources :products, only: [:show] do
    collection do
      get 'search'
    end

$ rails routes

search_products GET /products/search(.:format) products#search

上記のようなprefixが定義されます。


とりあえず便利なオプションは使っとけ!



getやpostだらけのルーティングでは可読性も下がってしまうので、
resourcesやmember、collectionを用いて、読みやすいルーティングを定義するように心がけます、、、


参考にさせていただいたサイト
Railsで自動生成以外のrouteを追加する - Qiita
【Ruby on Rails】ルーティング member と collection の違い - きゃまなかのブログ
collectionとmemberのルートのちがい rails - Prog-me.