背景
- Railsチュートリアル完走後に、**どのようにして機能を拡張していくか考えたときになんとなく「機能をリソース」として扱えれば、設計がしやすいのでは?**というのが発端。また、リソースについてもしっかり理解できていなかったので完走したあとに再度情報整理したかった。
目的
- 「Railsにおけるリソース」について、構成する要素の関係性についてまとめることで理解を深めてオペレーション時にもすぐに活かせる状態にしたい。
RESTの原則
- RailsはRESTの原則に従って設計されている。
- RESTとは、ざっくりいうとwebを設計するための考え方のひとつ。
- Railsでのリソースを理解するためには、土台であるRESTの原則を知る必要がある。
4つの原則
- ステートレスなクライアント/サーバプロトコル
- すべての情報(リソース)に適用できる「よく定義された操作」のセット
- リソースを一意に識別する「汎用的な構文」
- アプリケーションの情報と状態遷移の両方を扱うことができる「ハイパーメディアの使用」
引用元:Representational State Transfer - Wikipedia
1. ステートレスなクライアント/サーバプロトコル
RESTな考え方では、サーバーへのリクエストも、クライアントへのレスポンスも毎回状態を管理しない(ステートレス)HTTPを使う。
メリットとしては、複数のサーバーで複数のクライアントに対してレスポンスする際に効率がよい。
web設計する際に1つ目の原則に関しては、基本的にHTTPを使っていれば意識しなくて遵守される。
HTTP(HTTP/1.1)には、8つのメソッドが定義されており、2つ目の原則と関連してくる。
- GET
- POST
- PUT
- HEAD
- DELETE
- OPTIONS
- TRACE
- CONNECT
引用元:Hypertext Transfer Protocol - Wikipedia
2. すべての情報(リソース)に適用できる「よく定義された操作」のセット
RESTな考え方では、全てのリソースにHTTPメソッド(GET、POST、PUT、DELETEなど)を使ったアクセス可能な共通インターフェイスを持つ。
HTTPメソッドは次の役割を持っており、この役割に当てはめて設計を考える。
HTTPメソッド | 役割 |
---|---|
GET | リソースの取得 |
POST | 子リソースの作成、リソースへのデータ追加、その他の処理 |
PUT | リソースの更新、リソースの作成 |
DELETE | リソースの削除 |
HEAD | リソースのヘッダ(メタデータ)の取得 |
OPTIONS | リソースがサポートしているメソッドの取得 |
TRACE | 自分宛にリクエストメッセージを返す(ループバック)試験 |
CONNECT | プロキシ動作のトンネル接続への変更 |
3. リソースを一意に識別する「汎用的な構文」
RESTな考え方では、全てのリソースはURI(広い概念でURLとURNが含まれる)で表されるユニークなアドレス持つ
4. アプリケーションの情報と状態遷移の両方を扱うことができる「ハイパーメディアの使用」
今ではHTMLページに他のページへのリンクを貼ることは当たり前だが、そのこと。
これも、意識してなくても基本的に遵守される。
RESTfulとは
4つの原則に従って作成されたものを指す。
RailsでRESTfulなリソースを作成するために意識すること
Railsにおいて、RESTの原則の1と4に関しては、現在であれば当たり前なのであまり意識せずともよいが、2と3に関しては意識する必要がある。
2. すべての情報(リソース)に適用できる「よく定義された操作」のセット
Railsにおいて、2に関しては、具体的にRailsチュートリアル内のコラム 2.2で言及されており、
Railsのリソースは、下記に対応する共通インターフェイスを持っているといえる。
- リレーショナルデータベースの作成/取得/更新/削除 (Create/Read/Update/Delete: CRUD) 操作
- 4つの基本的なHTTPメソッド (POST/GET/PATCH/DELETE)
Railsは、RESTの原則を取り入れいち早く対応しているフレームワークでもあり、共通インターフェイスを持たせるために、HTTPメソッドごとにデータベース上のCRUD操作と対応付けを定義している。
Railsのルーティング機能は、RESTの考え方を取り入れる上で、重要。
ルーティングでHTTPメソッドとアクションを紐づけ、webでのCRUD操作を実現する。
下記は、photosリソースの例(CRUD操作の列は、HTTPメソッドとデータベースの繋がりが分かりやすいように追加)。
HTTP動詞 | パス | コントローラ#アクション | 目的 | CRUD操作 |
---|---|---|---|---|
GET | /photos | photos#index | すべての写真の一覧を表示 | 取得(R) |
GET | /photos/new | photos#new | 写真を1つ作成するためのHTMLフォームを返す | 取得(R) |
POST | /photos | photos#create | 写真を1つ作成する | 作成(C) |
GET | /photos/:id | photos#show | 特定の写真を表示する | 取得(R) |
GET | /photos/:id/edit | photos#edit | 写真編集用のHTMLフォームを1つ返す | 削除(D) |
PATCH/PUT | /photos/:id | photos#update | 特定の写真を更新する | 更新(U) |
DELETE | /photos/:id | photos#destroy | 特定の写真を削除する | 削除(D) |
引用元:Rails のルーティング - Rails ガイドの2.2の表参照
HTTPメソッドとURL(パス)を組み合わせて、CRUD操作を実現していることがわかる。
Railsの良いところは、resources :photos
を使えば、RESTの考え方に沿った共通インターフェイスができる点。
3. リソースを一意に識別する「汎用的な構文」
RESTの原則の3に関しては、Railsチュートリアルの7章の7.1.2 Usersリソースで少し触れられています。
RESTの原則に従う場合、リソースへの参照はリソース名とユニークなIDを使うのが普通です。
他にチュートリアルで良い例が見つけられなかったが下記が参考になった。
- URLに動詞を含めず、複数形の名詞のみで構成する
リソースを2.2.2 MVCの挙動のMVCモデルの図と使って説明
これらを踏まえた上で、自分のリソースのイメージは、こんな感じです。
図でいうと、ユーザーから見たインターフェイスは/usersになる。
/usersのページのリクエスト(HTTPメソッド)を元にCRUD操作と結びつける(ルーターとコントローラの役割。モデルも密接に関わっている)。
CRUD操作をするためには、データモデルが必要になり、最終的にユーザーから見える/usersに提供するためにビューが必要になる。
これらが組み合わさり、ユーザーにCRUD操作を提供するオブジェクトがリソース。これがリソースの正体。
Railsチュートリアルで出てきたリソースを比較してみる。
一番やりかったのがこれ。
下記ページのP25をみたときに全体像が分かっていれば、少しリソースの設計がわかりやすくと思ったため。
Rest ful api設計入門
3章以降で出てくるリソースをRailsのCRUD操作に当てはめてみた(自分が分かりやすいように少し調整)。
1~3行目までは、すべてのリソースに共通する項目で、4行目は、途中で説明したphotosリソースを例として使っている。5行目以降がRailsチュートリアルで出てくるリソース。
すべてのアクションを使っていないリソースがあったり、用途に合わせてパスを調整しているリソースもあったりすることがわかる。
目的 | 一覧表示 | 作成フォーム | 作成 | 個別表示 | 編集フォーム | 個別更新 | 個別削除 |
---|---|---|---|---|---|---|---|
HTTPリクエスト | GET | GET | POST | GET | GET | PATCH/PUT | DELETE |
対応アクション | index | new | create | show | edit | update | destroy |
photos | /photos | /photos/new | /photos | /photos/:id | /photos/:id/edit | /photos/:id | /photos/:id |
users | /users | /signup | /signup | /users/:id /users/:id/following /users/:id/followers |
/users/:id/edit | /users/:id | /users/:id |
sessions | - | /login | /login | - | - | - | /logout |
account_activations | - | - | - | - | account_activations#edit | - | - |
password_resets | - | /password_resets/new | /password_resets | - | /password_resets/:id/edit | /password_resets/:id | - |
microposts | - | - | /microposts | - | - | - | /microposts/:id |
relationships | - | - | /relationships | - | - | - | /relationships/:id |
まとめ
最後は、良くわからない表になってしまったがなんとなくでしか分からなかったリソースの全体像がわかったと思う。
なにより必要に応じて、分かりやすいように名前付きルートの変更(users/newをsignup)をしている点や全てのアクションを使わなくてもリソースの考え方に則って実装することで、リソースとして扱うという実装方法の統一が図れるという点、14章で出てくるフォローの実装はさらにRESTのリソースをより活用した実装(ルーティングをネストさせている)という点に気づけた。
参考
Representational State Transfer - Wikipedia
ステートフル ステートレスとはどういうことか - Sojiro’s Blog
Hypertext Transfer Protocol - Wikipedia
Representational State Transfer (REST)
「Webを支える技術」を読みました とRESTのまとめ - 大学生からの Web 開発
URLとURIは何が違うの? どちらが正しい呼び方? | 初代編集長ブログ―安田英久 | Web担当者Forum
RESTful-APIのURL設計を考えてみる - Qiita