RailsでREST API設計するときに知っておきたい集

## RESTについて

- RESTとは
    - Representational State Transfer。WebAPIの共通仕様、アーキテクチャスタイル。またはそれを用いたシステム。
- RESTfulとは
    - RESTの設計原則に従ったシステムのこと。

[Representational State Transfer - Wikipedia](https://ja.wikipedia.org/wiki/Representational_State_Transfer)

### RESTの設計原則

#### 1. ステートレス(Stateless)

- サーバ側で状態の管理を行わない。
- クライアントが送信するHTTPリクエストには、サーバがそのリクエストを処理するために必要な情報が全て含まれており、以前のリクエスト情報にも依存しない。
- セッション情報を保持しない。
    - だが、クッキー等によるセッション状態の管理を行なっているシステムもRESTfulと呼ばれる。

#### 2. 統一インターフェース(Uniform Interface)

- 1つのリソースに対してHTTPメソッドの定義通り(`GET`/`POST`/`PUT`/`DELETE`)に使われること。
- CRUDと(ある程度)対応する。
- HTTPメソッドは「**動詞**」で表される。

#### 3. アドレス指定可能(Addressability)

- 全ての情報はURIで表現される一意なアドレスを持っていること。
- 提供する情報がURIを通して表現できること。

#### 4. リンクと接続可能(Connectability)

- システムで使われるHTMLに他のリソースへのリンクを含めることができ、参照するにはリンクを辿るだけで良いこと。

[REST入門 基礎知識 - Qiita](https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa)
[ステートレスとは何か](http://yohei-y.blogspot.com/2007/10/blog-post.html)
[RESTful APIとは何なのか - Qiita](https://qiita.com/NagaokaKenichi/items/0647c30ef596cedf4bf2)
[RESTまとめ - Qiita](https://qiita.com/yokoto/items/143cc0e2fa05a7148520)
[フロントエンド開発者の僕にもやっとわかった！RESTfulの本当の意味](https://www.webprofessional.jp/what-does-restful-really-mean/)

## HTTPステータスコード

[RESTful APIのHTTPステータスコード設計 - Qiita](https://qiita.com/NagaokaKenichi/items/eb85b5fbb719d60c6627)
[処理結果をHTTPステータスコードで返す - Qiita](https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa#%E5%87%A6%E7%90%86%E7%B5%90%E6%9E%9C%E3%82%92http%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%81%A7%E8%BF%94%E3%81%99)

## リソースについて

- Web上に存在する情報、データのこと。
- コンピュータ上に格納することができ、一連のビットで表現できる。
- また、それ自体を参照するに値するほどの重要性を持っている。
    - 例: ドキュメント、データベースの行等。
- リソースは「**名詞**」で定義される。

[リソース指向アーキテクチャ(ROA)とは何なのか - Qiita](https://qiita.com/NagaokaKenichi/items/0f3a55e422d5cc9f1b9c)

## RESTful API設計のステップ

1. 対象となるデータを認識する
1. 対象となるデータをリソースに分ける
1. リソースにURLで名前を付ける
1. リソースに対してGET/POST/PUT/DELETEをマッピングする
1. クライアントから受信する表現を設計する
1. クライアントに提供する表現を設計する
1. ハイパーメディアリングとフォームを使用して、既存のリソースと統合する(接続性を高める)
1. 正常系を考える
1. 例外条件を考える

[RESTful Web アプリの設計レビューの話](https://pdfslide.net/reader/f/restful-web-)

## RailsとREST

- RESTfulであることは、Railsの規約である[リソースベースのルーティング](https://railsguides.jp/routing.html#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0-rails%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88)に沿うことのように思う。
- Railsにおいて「リソースフルなルーティング」と言う時、以下によって構成されるルーティングのことを指す。
    - 4種類のURL（/photos、/photos/new、/photos/:id、/photos/:id/edit）
    - 7種類の異なるアクション（index、show、new、create、edit、update、destroy）

| HTTP verb | パス | コントローラ#アクション | 目的 |
|:-:|:-:|:-:|:-:|
| GET | /photos | photos#index | すべての写真の一覧を表示 |
| GET | /photos/new | photos#new | 写真を1つ作成するためのHTMLフォームを返す |
| POST | /photos  | photos#create | 写真を1つ作成する |
| GET | /photos/:id | photos#show | 特定の写真を表示する |
| GET | /photos/:id/edit | photos#edit | 写真編集用のHTMLフォームを1つ返す |
| PATCH/PUT | /photos/:id | photos#update | 特定の写真を更新する |
| DELETE | /photos/:id | photos#destroy  | 特定の写真を削除する |

[RESTとRailsスタイル](https://www.slideshare.net/tkawa1/restrails)

## Railsのリソース設計パターン

### 基本系

- Collectionリソース
    - `/users`
    - `resources` で表す。
- Memberリソース
    - `/users/:id`
    - `resources` で表す。
- Singular（単数）リソース
    - `/user`
    - `resource` で表す。
- 補助リソース
    - `/users/new`
    - HTMLのUIのために必要となる。
- アルゴリズムリソース
    - `/users?q={query}`
    - クエリパラメータによるアルゴリズムの実行のために必要となる。
- 静的リソース
    - JavaScriptやCSS。
- ルートリソース
    - `/`

### 具体系

- Filtered Collectionパターン
    - `/users?q={query}`
    - Collectionリソース + アルゴリズムリソース。
    - 例: ページネーション。
- Filtered SubResourceパターン
    - `/users/admin`
    - コレクションリソースの一種。
- Multi-member Resourceパターン
    - `/users/1-2-3` , `/users/1,2,3`
    - Memberリソースの派生系。
- Partial Resourceパターン
    - `users/:id/email,name`
- Transaction Resourceパターン
    - `/users` , `/users/:id` , `/users/:id/committed`
    - Collectionリソース + Memberリソース。
- Session Resourceパターン
    - `/session`
        - 認証のセッション自体をリソースと捉える。
        - モデルではないリソースの典型。
    - 例: Devise gemなど。
- Private Resource(Namespace)パターン
    - `/my/{resource}`
        - 人によって違うリソースを指すことを明示するために、名前空間を分ける。
    - Singularリソースの特別な場合。


[RailsでのURL設計を考えてみる(5) Railsのリソースパターン](https://tkawa.hatenadiary.org/entry/20111031/p1)
[「リソースモデリングパターンの提案」の先](https://tkawa.hatenadiary.org/entry/20120726/p2)
[『RESTful API の みつけかた』](https://shinkufencer.hateblo.jp/entry/2019/03/11/233000)

## Railsのコントローラ設計

- コントローラはデフォルトのCRUDアクション（`index`/`show`/`new`/`edit`/`create`/`update`/`destroy`）のみを使うべき。
    - 「重複は、[間違った抽象化](https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction)より負担が小さい」ため。
    - リソースベースのルーティングで設計できるため。

[DHHはどのようにRailsのコントローラを書くのか](https://postd.cc/how-dhh-organizes-his-rails-controllers/)

## RailsではPATCHかPUTどちらを用いるか

- Putメソッド
    - 置換。冪等。
    - 例: S3のURLへのファイルのアップロード。
- Patchメソッド
    - 既存のリソースの更新・変更・修正。
    - [Edge Rails: "PATCH is the new primary HTTP method for updates"](https://rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates)
    - 例: ユーザー情報更新。

[PatchとPutの違いについて - Qiita](https://qiita.com/murata0705/items/52538c08778c39a91ec2)

## Railsで複数のリソースにアクセスしたい時のURL設計

- 親と子のリソースを両方更新したい場合
    - 親に対するリクエストだけで済ませる。
- 複数のメンバリソースを更新したい場合
    - パフォーマンスの観点から、コレクションリソースを使って、リクエストボディで配列を送る = これをバルク更新と呼ぶ。

[複数のリソースに一度にアクセスしたいときのURL設計](https://tkawa.hatenadiary.org/entry/20120227/p2)
[複数のリソースをまとめて作成/更新/削除する場合のエンドポイントをどう作るか](https://note.com/yamarkz/n/n41e9ac83c896#1awJv)

## Railsの確認画面のURL設計

[RailsでのURL設計を考えてみる(3) 確認画面のURLは必要か](https://tkawa.hatenadiary.org/entry/20110627/p1)
[rails で確認画面を実装する](https://beyond.cocolog-nifty.com/akutoku/2011/05/rails-a0d6.html)
[Rails で確認画面を作る方法＜Perfect Edition＞](https://beyond.cocolog-nifty.com/akutoku/2016/03/rails-perfect-e.html)
[confirmationを使う場合にRESTfulっぽくなるようにしてみた](https://gist.github.com/kozo002/3224707)

## DB設計とリソース設計の関係性について

- リソースとDBのレコードは必ずしも対応しない。
- 見えないリソースを探し出すことが重要。
    - 関連エンティティ。
    - 処理(イベント)を表すリソース。

[1周遅めのリソース設計](https://speakerdeck.com/moro/rails-resource-routing-design-bootstrap-ja)


## クライアントサイドからAPI設計を考える

### RESTful API :+1:
- この記事で述べてきたようなリソースごとにエンドポイントを作っていく設計。
- アプリの画面と API の結合性が低くなり、生産性が上がる。
    - Web エンジニアがアプリの画面の詳細まで知らなくても設計ができる。
    - iOSとAndroidで実装状況が異なる場合にもAPIの中で条件分岐が必要ない。
- 一方で、あるエンドポイントが様々な画面で使われる「Chatty API」になる。

### 1 Screen, 1 API call :+1:
- APIで返すレスポンスデータを決定する際に、APIのアクセス回数がなるべく減るようにするという考え方がある。
    - 例: "ホーム画面専用" APIを作成し、それに１回アクセスするだけでホーム画面に表示するすべての情報が取得できる。

### Chatty API :thumbsdown: 

- Chatty APIとは、ひとつの作業を完了させるために複数回のアクセスが必要となるAPIのこと。
    - ネットワークのトラフィックを増加させ、クライアントの実装の手間も増やしてしまうためいいことなし。
- １画面を表示するのに、何度も異なるAPIにアクセスしなければならい場合のデメリット。
    - 速度の問題がある。
        - 非効率
        - 画面を表示するまでに時間もかかる
        - ユーザーを待たせる。
    - データの一部だけが表示されてしまう問題がある。

### Etc.
#### LUCDs向けのAPIとSSKDs向けのAPI

- LSUDs 向け・・・一般に公開し多くの人に使ってもらうための API
- SSKDs 向け・・・自社のスマホアプリなど、特定の人だけが使う API

SSKDs向けのAPIでは、必ずしも汎用的な美しいAPIを提供する必要はなく、ユーザ体験を考えると、ホーム画面に表示する情報を1つに詰め込んだ「1 screen 1 API call、1 save 1 API call」とした方が良い。

#### SPAのバックエンドとしてのRails API

- Railsアプリ本来のscaffold的なRESTful APIは、SPAのバックエンドとしては向いていない。
    - 「1 Screen, 1 API Call」ではないので、画面表示までに複数のAPIへリクエストを出さなければならないのが、SPAには不向き。
- SPA専用のAPIを1つ用意するのが良い。

[gushernobindsme/WebAPITheGoodParts_読書メモ.md](https://gist.github.com/gushernobindsme/45f848f3dba1b29a91c226b6298bcd1f)
[エンジニア戦記 〜小さなチーム、大きな未来〜](https://www.slideshare.net/susieyy/ios-ios-44665266)
[第26回 #ginzarb 参加レポート](https://dev.classmethod.jp/articles/ginzarb-meetup-26-report/)
[Rails 5 で作る RESTful API 速習会 / Rails RESTful API](https://speakerdeck.com/altech/rails-restful-api)
[Altech/rails-restful-api](https://github.com/Altech/rails-restful-api)

## Web API設計その他諸々

[Web APIとは何なのか - Qiita](https://qiita.com/NagaokaKenichi/items/df4c8455ab527aeacf02)
[翻訳: WebAPI 設計のベストプラクティス - Qiita](https://qiita.com/mserizawa/items/b833e407d89abd21ee72)
[REST API設計者のための有名APIのURL例 - Zenn](https://zenn.dev/yu1ro/articles/4c73274383b676)
[Web API: The Good Partsを読んだので「良いURI」についてまとめた - Qiita](https://qiita.com/soyanchu/items/34f8e164c24f044e80a3)
[そのリクエストパラメータ、クエリストリングに入れますか、それともボディに入れますか - Qiita](https://qiita.com/sakuraya/items/6f1030279a747bcce648)
[そのフィールド、nullable にしますか、requiredにしますか - Qiita](https://qiita.com/sakuraya/items/2d98c352c74ad72e2a9a)
[Rails における JSON のシリアライズと向き合う 🦜 - Qiita](https://qiita.com/sakuraya/items/924ec3c3001938071407)
[綺麗なAPI速習会 - Qiita](https://qiita.com/shimastripe/items/e9b0e1f8f8d77b89373f)
[RailsのAPI開発にスキーマ駆動開発を導入して、品質と開発スピードを高める - freee Developers Hub](https://developers.freee.co.jp/entry/schma-driven-api)
[スキーマ駆動でAPI開発を行う - SPACEMAEKET BLOG](https://blog.spacemarket.com/code/schema-driven/)