Railsと日々格闘している「超」がつく初心者です。
数週間前にテキストで見てから、ルーティングでresourcesを使えば、なんかよくわからんけどアクションとHTTPメソッドが紐付くんやな〜とまる覚えして、訳もわからないまま、resourcesと打ち込み続けてきました。
当然、そんなやり方&理解では詰まってしまう瞬間があったので、一度腰を据えてresources(複数形)とresource(単数形)に向き合おうと思い、この記事を書きました。
#そもそもresources(複数形)とは
リソースとは、データベースのテーブルに保存される、レコード1行分の情報のことです。
resourcesと1行記載するだけで、複数のルーティングが定義され、「RESTful」なアプリを作成することが出来る、スーパー便利な機能なのです。
もしもresourcesを使わなかった場合、
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を使用して、ルーティングを記載してみると、
Rails.application.routes.draw do
resources :tweets
end
ハイ終了。
ターミナルを確認してみると、
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を利用したルーティングの中身を見てみると、
Rails.application.routes.draw do
resource :tweet #resource(単数形)に合わせて、モデル名もtweetと単数形にしています!
end
パッと見、ルーティングの見た目はほとんど同じですね。
しかし、ターミナルを確認してみると、resources(複数形)を記述した時と違う部分がいくつかあることに気づきます。
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つあり、それは
①indexアクションがあるかないか
②urlに:idを含むかどうか
です。
ツイートには一覧機能が必要なので、使うならresourcesであるべきです。
しかし、例えばユーザーのプロフィールのように、indexで一覧表示する必要性が乏しいものについては、resourceを使用した方が良いのでしょう。
実際の運用では、単純な使い分けも難しいとは思いますが、簡単にいうと、
アプリ上に複数存在するリソースの場合 → resources
アプリ上にリソースが1つしか存在しない場合 → resource
のような理解で大丈夫だと思います。
#memberとcollection
じゃあ、これでresourcesとresourceの違いが分かった、もう百人力だ!
と粋がるのは2000万年早いです。
resourcesを利用して定義できるアクションは、上に登場している7つの主要なアクションだけです。
「フォロー機能をつけたいんやけど・・・」
「検索機能とかは無理なんかな・・・」
といった、7つの基本アクションから発展して機能を付けたい場合には、更に便利な機能
「member」 と 「collection」
があります。
#memberとは
ユーザー同士のフォロー機能を実装することを想像しましょう。
当然、Userモデル自体もresourcesを利用してルーティング定義ができます(アプリ上には複数のユーザーが存在するため)。
ユーザーのidを識別しつつ、それらを関連付け、idで指定した個々のリソースに対するアクションを設定します!
Rails.application.routes.draw do
resources :users do
get :follows, on: :member
get :followers, on: :member
end
end
ハイこれだけです。
ターミナルを確認すると、
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との相違点は、リソース全体に対するアクションを設定できるということです。
具体的に説明していきましょう。
ルーティングとしては、
Rails.application.routes.draw do
resources :users do
get :search, on: :collection
end
end
恒例行事になってきました。ターミナルを確認しましょう。
search_users GET /users/search(.:format) users#search
#以下、7つのアクション分は省略
collectionを使用した場合、urlに:idが含まれることなく、searchアクションへルーティングができています。
#おわりに
長々とまとまりのない説明にお付き合いくださり、ありがとうございました。
自分自身も説明しながら、理解が深まった部分もあったので、使えば使うほど体に染み込んでいくのかと思っています。
皆様のプログラミング勉強の一助となればこれ幸いです。