Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

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

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

そもそもresources(複数形)とは

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

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

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を使用して、ルーティングを記載してみると、

routes.rb
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を利用したルーティングの中身を見てみると、

routes.rb
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で指定した個々のリソースに対するアクションを設定します!

routes.rb
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との相違点は、リソース全体に対するアクションを設定できるということです。
具体的に説明していきましょう。

ルーティングとしては、

routes.rb
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アクションへルーティングができています。

おわりに

長々とまとまりのない説明にお付き合いくださり、ありがとうございました。
自分自身も説明しながら、理解が深まった部分もあったので、使えば使うほど体に染み込んでいくのかと思っています。
皆様のプログラミング勉強の一助となればこれ幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away