ぼくがかんがえたさいきょうのRails API開発環境

今やっているバイトでRails APIを作成しています。
APIを作成する際に、以下のような問題点が出てきました。

1. APIのdocumentがないとフロントエンドの開発者が開発しづらい
2. documentを書くのにopenapiを採用するが、文法を覚えるのに一苦労するし、見づらいので書き忘れが生じる。
2. API responseの構造に開発者間で違いが出てしまう。
3. 実際のAPIとdocumentの挙動が違うのに修正を忘れてしまう

## 結論

結論から言うと、これらの問題を解決するために以下のようにしました。

1. APIのPRを出す時にopenapiでdocumentを書く。
2. SpotlightStudioを使ってopenapiを書く。
2. responseの形はJsonAPIに従い、gemにfastjsonapiを導入する。
3. committeeというgemを使って実際の挙動とopenapiに書かれていることが違っていないか自動テストする。

## Openapi(元々はSwaggerという名前)を使う

https://swagger.io/specification/

RESTful APIのdocumentを書く時には、調べた感じだとこれ一択のような印象を受けました。
Openapiの書き方に従うことで、以下のメリットがあることを感じました。

- documentの書き方が統一される
- 実装を始める前にdocumentを書くことで、実装の見通しが立てやすくなる
- フロントエンドの開発者からAPIの実装を要求された時に、Openapiで欲しい仕様を書いてもらうことで、効率的にコミュニケーションができる。

## Spotlight Studioを使ってOpenAPIを書く

これが無ければ、OpenAPIを書くことがかなりの負担になって開発効率を下げていたと思っています。
OpenAPIを実際に使い始めると、以下の問題点が出てきました。

- YAMLでの文法を覚えるがめんどくさい
- ここインデント入れるんだっけ？とか確認する手間が出る
- 文法を全部調べるのが手間だから、知らないままの便利な書き方が、知らないままになる

<img width="902" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202653/40a52cc1-b715-fae7-3d3e-116a6b09ed89.png">

引用：[公式ページ](https://stoplight.io/p/docs/gh/stoplightio/studio/docs/ui-overview.md?srn=gh/stoplightio/studio/docs/ui-overview.md)

Spotlight Studioを使うことで、上の画像のようにGUIベースでOpenAPIを作成することができます。
これにより、OpenAPIの文法を覚える必要がありませんし、タイポしてエラーが出ることもありません。

[本当に使ってよかったOpenAPI (Swagger) ツール](https://future-architect.github.io/articles/20191008/)

## JsonAPI

https://jsonapi.org/format/

APIのresponseの形にもルールがないと、フロントエンド側で取り扱いが難しくなってしまいます。
JSONはシンプルで扱いやすい反面、自由度が高いです。
そこでルールを取り入れることで、開発がしやすいようにする必要があります。

[Web APIにはJSONベースのフォーマットを使おう](https://qiita.com/tkawa/items/2841e155e5b51c09ed40)

上の記事に書いてありますが、JSONベースのAPIには様々な仕様があります。
私が行った開発はでJsonAPIを使うことにしました。
それはNetflixが提供している、fastjsonAPIというgemが使いやすそうだったからです。
公式の計測によると、Active Model Serrializersに比べて25倍も早いそうです。

https://github.com/Netflix/fast_jsonapi

> We compare serialization times with Active Model Serializer as part of RSpec performance tests included on this library. We want to ensure that with every change on this library, serialization time is at least 25 times faster than Active Model Serializers on up to current benchmark of 1000 records. Please read the performance document for any questions related to methodology.

シリアライザーを使うことのメリットとしては、
- 以下のようなデータ構造の使い回しがしやすい。
- シリアライザーに対応した定義をOpenAPI側にも容易すれば、OpenAPI書くときも楽

というメリットがありました。

```yaml

{
  "data": {
    "id": "3",
    "type": "movie",
    "attributes": {
      "name": "test movie",
      "year": null
    },
    "relationships": {
      "actors": {
        "data": [
          {
            "id": "1",
            "type": "actor"
          },
          {
            "id": "2",
            "type": "actor"
          }
        ]
      },
      "owner": {
        "data": {
          "id": "3",
          "type": "user"
        }
      }
    }
  }
}
```

## committee gemでOpenAPIをテストする

せっかくOpenAPIを用意するようにしても、APIの仕様を変更した時にOpenAPIの修正を忘れることは十分に考えられます。
これを防ぐために、committee gemを導入してOpenAPIの内容と実際のAPIの挙動が一致するかのテストをすることにしました。

https://github.com/interagent/committee

Railsでcommitteeを使うには、committee-railsというgemを使うのが一番楽だと感じました。
committeeをrailsで簡単に使えるようにwrapしたものが、committee-railsになります。

https://github.com/willnet/committee-rails

しかしcommitteeはrequestとresponseの中でrequiredになっているものを検証するみたいです。
committeeが通っているから、OpenAPIが実際のAPIを反映しているとは言い難いというのは、微妙なのでここは改善したいです。