[Rails] resourcesとresourceの違いについて勉強してみた

Railsと日々格闘している「超」がつく初心者です。
数週間前にテキストで見てから、ルーティングでresourcesを使えば、なんかよくわからんけどアクションとHTTPメソッドが紐付くんやな〜とまる覚えして、訳もわからないまま、resourcesと打ち込み続けてきました。

当然、そんなやり方&理解では詰まってしまう瞬間があったので、一度腰を据えてresources(複数形)とresource(単数形)に向き合おうと思い、この記事を書きました。

#そもそもresources(複数形)とは
リソースとは、データベースのテーブルに保存される、レコード1行分の情報のことです。
resourcesと1行記載するだけで、複数のルーティングが定義され、「RESTful」なアプリを作成することが出来る、スーパー便利な機能なのです。

もしもresourcesを使わなかった場合、

```ruby:routes.rb
Rails.application.routes.draw do
  get 'tweets'     => 'tweets#index'
  get 'tweets/:id' => 'tweets#show'
  get 'tweets/new' => 'tweets#new'
  post 'tweets' => 'tweets#create'
  get 'tweets/:id/edit' => 'tweets#edit'
  patch 'tweets/:id'  => 'tweets#update'
  delete 'tweets/:id' => 'tweets#destroy'
end
```

という記載を全て手入力しないといけなくなり、非常にメンドいです。
これだけで半日ぐらい潰れそうな勢いでメンドいです。

そこで、噂のresourcesを使用して、ルーティングを記載してみると、

```ruby:routes.rb
Rails.application.routes.draw do
  resources :tweets
end
```

ハイ終了。
ターミナルを確認してみると、

```ruby:ターミナル
tweets     GET    /tweets(.:format)          tweets#index
           POST   /tweets(.:format)          tweets#create
new_tweet  GET    /tweets/new(.:format)      tweets#new
edit_tweet GET    /tweets/:id/edit(.:format) tweets#edit
tweet      GET    /tweets/:id(.:format)      tweets#show
           PATCH  /tweets/:id(.:format)      tweets#update
           PUT    /tweets/:id(.:format)      tweets#update
           DELETE /tweets/:id(.:format)      tweets#destroy
```

と見事に、CRUD処理を行うためのルーティングが完成されているではありませんか。
これは便利だぞ。
#それならresource(単数形)とは?
さあここで頭を悩ませる奴の登場です。
実は複数形だけでなく、単数形で記載するresourceという方法もあるのです。
とにかく確認してみましょう。

実際に、resourceを利用したルーティングの中身を見てみると、

```ruby:routes.rb
Rails.application.routes.draw do
  resource :tweet #resource(単数形)に合わせて、モデル名もtweetと単数形にしています！
end
```

パッと見、ルーティングの見た目はほとんど同じですね。
しかし、ターミナルを確認してみると、resources(複数形)を記述した時と違う部分がいくつかあることに気づきます。

```ruby:ターミナル
new_tweet  GET    /tweet/new(.:format)   tweets#new
edit_tweet GET    /tweet/edit(.:format)  tweets#edit
tweet      GET    /tweet(.:format)       tweets#show
           PATCH  /tweet(.:format)       tweets#update
           PUT    /tweet(.:format)       tweets#update
           DELETE /tweet(.:format)       tweets#destroy
           POST   /tweet(.:format)       tweets#create
```

#resourcesとresourceの相違点について
大きな違いは2つあり、それは
<strong>①indexアクションがあるかないか
②urlに:idを含むかどうか</strong>
です。

ツイートには一覧機能が必要なので、使うならresourcesであるべきです。
しかし、例えばユーザーのプロフィールのように、indexで一覧表示する必要性が乏しいものについては、resourceを使用した方が良いのでしょう。

実際の運用では、単純な使い分けも難しいとは思いますが、簡単にいうと、
アプリ上に複数存在するリソースの場合　→　resources
アプリ上にリソースが1つしか存在しない場合　→　resource
のような理解で大丈夫だと思います。
#memberとcollection
<strong>じゃあ、これでresourcesとresourceの違いが分かった、もう百人力だ！</strong>
と粋がるのは2000万年早いです。
resourcesを利用して定義できるアクションは、上に登場している7つの主要なアクションだけです。

「フォロー機能をつけたいんやけど・・・」
「検索機能とかは無理なんかな・・・」
といった、7つの基本アクションから発展して機能を付けたい場合には、更に便利な機能
<strong>「member」　と　「collection」</strong>
があります。
#memberとは
ユーザー同士のフォロー機能を実装することを想像しましょう。
当然、Userモデル自体もresourcesを利用してルーティング定義ができます(アプリ上には複数のユーザーが存在するため)。

ユーザーのidを識別しつつ、それらを関連付け、idで指定した個々のリソースに対するアクションを設定します！

```ruby:routes.rb
Rails.application.routes.draw do
  resources :users do
    get :follows, on: :member
    get :followers, on: :member
  end
end
```

ハイこれだけです。
ターミナルを確認すると、

```ruby:ターミナル
follows_user    GET   /users/:id/follows(.:format)　   users#follows
followers_user  GET   /users/:id/followers(.:format) 　users#followers
#以下、7つのアクション分は省略
```

ものの見事に、userのidを含んだ形で、個々のリソースに対してfollowsアクションとfollowersアクションが設定できています！
#collectionとは
続いて、このままcollectionへと移ります。
memberとの相違点は、リソース全体に対するアクションを設定できるということです。
具体的に説明していきましょう。

ルーティングとしては、

```ruby:routes.rb
Rails.application.routes.draw do
  resources :users do
    get :search, on: :collection
  end
end
```

恒例行事になってきました。ターミナルを確認しましょう。

```ruby:ターミナル
search_users   GET    /users/search(.:format)    users#search
#以下、7つのアクション分は省略
```

collectionを使用した場合、urlに:idが含まれることなく、searchアクションへルーティングができています。
#おわりに
長々とまとまりのない説明にお付き合いくださり、ありがとうございました。
自分自身も説明しながら、理解が深まった部分もあったので、使えば使うほど体に染み込んでいくのかと思っています。
皆様のプログラミング勉強の一助となればこれ幸いです。