railsのルーティングからOpenAPI(V3)ドキュメントを自動生成・管理するツールを作成し、10ヶ月間会社で運用した話(下期編)

前回、[railsのルーティングからOpenAPI(V3)ドキュメントを自動生成・管理するツールを作成し、4ヶ月間会社で運用した話(開発秘話もあるよ)
](https://qiita.com/yukihirop/items/670e843a1cdf50621ca8)という記事で下期の進捗も報告すると書いたのでその記事になります。

## 使用したツール

自分で作った<a href="https://rubygems.org/gems/r2-oas" _target="blank" rel="noreopener">`r2-oas`</a>です。

![oas_editor](https://user-images.githubusercontent.com/11146767/80364657-4079a100-88c1-11ea-8f56-c9af78829d68.gif)

## 4ヶ月の実績

※会社の許可をとりデータを載せております。

## 全体の実績

赤線が目標ライン。目標は、5個/週 です。

![スクリーンショット 2020-03-30 11.04.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113181/548231cd-3c35-270c-f988-d55023af9376.png)

## 各週の実績

10月の中旬に進捗がないのは、他のプロジェクトを引き継ぐために必死だったからです。
着手する余力がなかったです。12/30の週に進捗がないのは正月休み。その他進捗がなかったのは


![スクリーンショット 2020-03-30 11.04.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113181/abe89cdf-a7fd-8517-bc1d-05faa3eb9492.png)

## 個人の実績

チームとの話し合いでAPIドキュメント書いていくのはシンドイとなったので個人でコツコツやってました。

私の9ヶ月の進捗実績は、`7.56個/週`でした。
下期だけの進捗だと `3.8個/週`でした。

最初、`週10個/週`を目標にやっていたおかげもあってそんなにひどい結果にならずにすんだとはいえ、目標未達成です。

残念です。

<img width="1307" alt="スクリーンショット 2020-03-30 10.57.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113181/ddc40c05-5ab4-d338-b892-67fe907cecd2.png">

## 進捗管理表

これまで乗せてきたグラフや表はこの進捗管理表から自動生成されてます。
pathsファイル というのがrailsで言うところのコントローラーに対応してます。
後で紹介しますが、r2-oas は「コントローラー毎にAPIドキュメントが書ける」特徴があります。

<img width="1103" alt="スクリーンショット 2020-03-30 11.02.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113181/1f5c1be0-409f-ce64-ed0c-613f2fa42654.png">

## まとめ

下期は個人でコツコツやってました。途中でなげだすのはよくないと思うので、上司と話あって継続で`5個/週`でやっていきます。

|項目|実績/目標|
|---|--------|
|個人合計(個)|189個|
|個人平均(個/週)|7.58個/週|
|下期個人平均(個/週)|3.8個/週|

## r2-oasのチュートリアル

`r2-oas` ってなんだよ。って人向けのチュートリアルです。r2-oasが得意とすることは既に完成されたAPIのAPIドキュメントを自動で作成することです。そしてコードベースで書いていかないので、途中からでも始められるし、途中でやめやすいというのが特徴です。

rails6でAPIドキュメントを作ってみましょう。

SwaggerUIやSwaggerEditorで開いたりする場合は以下の準備が必要です。

```bash
$ brew cask install chromedriver
$ docker pull swaggerapi/swagger-ui:latest
$ docker pull swaggerapi/swagger-editor:latest
```

rails newしたら、Gemfileのdevelopmentに `r2-oas` を追加してください。

```ruby
group :development do
 gem 'r2-oas'
end
```

### 準備

```bash
$ rails _6.0.0_ new example-600 -d mysql --skip-bundle
$ cd example-600
$ bundle install --path vendor/bundle
$ # mysql2のエラーが出るときは以下を実行して、bundle installをやり直す。
$ # bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
```

scaffoldで適当にルーティングを作成する。

```bash
$ bundle exec rails g scaffold user name:string age:integer
$ bundle exec rails g scaffold task status:string content:string
$ bundle exec rails g scaffold Api/V1/Account status:string content:string
$ bundle exec rails g scaffold Api/V2/CustomPost status:string content:string
```

一旦コミットする

```bash
$ git init
$ git add . && git commit -nm "initial commit "
$ # OpenAPI(V3)形式のドキュメントの雛形生成
$ bundle exec rake routes:oas:docs
# ドキュメントはコロコロ変わるのでgitignoreに追加する。
$ echo 'oas_docs/oas_doc.yml' >> .gitignore
$ # 一旦コミットする
$ git add . && git commit -nm "generate docs"
```

SwaggerEditor(UI)で開く。 `PATHS_FILE` という環境変数を指定したほうが最小限のドキュメントだけビルドされるので動作は軽いです。

```bash
$ bundle exec rake routes:oas:editor
$ # もしくは
$ # こんな風にpathsファイル毎に開くこともできます。環境変数のPATHS_FILEを指定します。
$ PATHS_FILE=oas_docs/src/paths/task.yml bundle exec rake routes:oas:editor
```

ここでは `PATHS_FILE` を指定して開いてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113181/98fa08a5-a3c6-8280-72ce-e4a137cda012.png)

- `GET /tasks` の `summary` を「タスク一覧取得」に修正
- `GET /tasks` の `422` に関しての情報をすべて削除

以上ができたら、ターミナルに戻り `Ctrl+C` を押してみましょう。

```bash
wait for signal trap ...
^CI, [2020-03-30T11:52:20.903111 #21328]  INFO -- : [Analyze OAS file] start
I, [2020-03-30T11:52:20.908564 #21328]  INFO -- : [Analyze OAS file (tags)] start
I, [2020-03-30T11:52:20.910406 #21328]  INFO -- :   Write schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/tags.yml
I, [2020-03-30T11:52:20.910440 #21328]  INFO -- : [Analyze OAS file (tags)] end
I, [2020-03-30T11:52:20.910450 #21328]  INFO -- : [Analyze OAS file (paths)] start
I, [2020-03-30T11:52:20.915803 #21328]  INFO -- :   Write schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/task.yml
I, [2020-03-30T11:52:20.915851 #21328]  INFO -- : [Analyze OAS file (paths)] end
I, [2020-03-30T11:52:20.915865 #21328]  INFO -- : [Analyze OAS file (components)] start
I, [2020-03-30T11:52:20.915883 #21328]  INFO -- : [Analyze OAS file (components/schemas)] start
I, [2020-03-30T11:52:20.918129 #21328]  INFO -- :   Write schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/components/schemas/task.yml
I, [2020-03-30T11:52:20.918168 #21328]  INFO -- : [Analyze OAS file (components/schemas)] end
I, [2020-03-30T11:52:20.918182 #21328]  INFO -- : [Analyze OAS file (components/requestBodies)] start
I, [2020-03-30T11:52:20.920313 #21328]  INFO -- :   Write schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/components/requestBodies/task.yml
I, [2020-03-30T11:52:20.920364 #21328]  INFO -- : [Analyze OAS file (components/requestBodies)] end
I, [2020-03-30T11:52:20.920381 #21328]  INFO -- : [Analyze OAS file (components/securitySchemes)] start
I, [2020-03-30T11:52:20.920889 #21328]  INFO -- : [Analyze OAS file (components/securitySchemes)] end
I, [2020-03-30T11:52:20.920908 #21328]  INFO -- : [Analyze OAS file (components/parameters)] start
I, [2020-03-30T11:52:20.921348 #21328]  INFO -- : [Analyze OAS file (components/parameters)] end
I, [2020-03-30T11:52:20.921365 #21328]  INFO -- : [Analyze OAS file (components/responses)] start
I, [2020-03-30T11:52:20.921804 #21328]  INFO -- : [Analyze OAS file (components/responses)] end
I, [2020-03-30T11:52:20.921820 #21328]  INFO -- : [Analyze OAS file (components/examples)] start
I, [2020-03-30T11:52:20.922285 #21328]  INFO -- : [Analyze OAS file (components/examples)] end
I, [2020-03-30T11:52:20.934988 #21328]  INFO -- : [Analyze OAS file (components/headers)] start
I, [2020-03-30T11:52:20.940521 #21328]  INFO -- : [Analyze OAS file (components/headers)] end
I, [2020-03-30T11:52:20.940773 #21328]  INFO -- : [Analyze OAS file (components/links)] start
I, [2020-03-30T11:52:20.944804 #21328]  INFO -- : [Analyze OAS file (components/links)] end
I, [2020-03-30T11:52:20.944943 #21328]  INFO -- : [Analyze OAS file (components/callbacks)] start
I, [2020-03-30T11:52:20.945420 #21328]  INFO -- : [Analyze OAS file (components/callbacks)] end
I, [2020-03-30T11:52:20.945540 #21328]  INFO -- : [Analyze OAS file (components)] end
I, [2020-03-30T11:52:20.945569 #21328]  INFO -- : [Analyze OAS file] end
I, [2020-03-30T11:52:21.162340 #21328]  INFO -- : container id: fddeedcd579c4e53ec549778ae5dc3888796b011543e504f77b93706d4dac232 removed
I, [2020-03-30T11:52:21.162463 #21328]  INFO -- : [R2-OAS] end
```

こんな感じにログが流れて差分を確認すると以下の様になっているはずです。

![image](https://user-images.githubusercontent.com/11146767/78016559-f070f280-7385-11ea-87df-8884ead6cd95.png)


これをcommitしましょう。

```bash
git add . && git commit -nm "Write GET /tasks"
```

このようにAPIドキュメントを書いていきます。

## 完成したAPIドキュメントだけ表示したい

そういう場合もあるでしょう。そのためにr2-oasには、`.paths` ファイルに完成したpathsのyamlファイルを書いていきます。

今、`oas_docs/src/paths/task.yml` が完成したとすると、

```bash
# pathsディレクトリ以下の相対パスを書きます。
echo 'task.yml' >> .paths
```

こうすることで環境変数のPATHS_FILEが指定される時以外は、`oas_docs/src/paths/task.yml`に関してのAPIドキュメントに関してだけしか表示されなくなります。

```bash
$ bundle exec rake routes:oas:ui
I, [2020-03-30T12:00:39.428227 #22297]  INFO -- : [R2-OAS] start
I, [2020-03-30T12:00:39.543178 #22297]  INFO -- : [Generate OAS schema files] start
I, [2020-03-30T12:00:39.543224 #22297]  INFO -- : [Generate OAS schema files] end
I, [2020-03-30T12:00:39.543237 #22297]  INFO -- : [Generate OAS docs from schema files] start
I, [2020-03-30T12:00:39.543595 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/openapi.yml
I, [2020-03-30T12:00:39.543683 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/external_docs.yml
I, [2020-03-30T12:00:39.543797 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/tags.yml
I, [2020-03-30T12:00:39.543882 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/info.yml
I, [2020-03-30T12:00:39.544091 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/servers.yml
I, [2020-03-30T12:00:39.544328 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/task.yml
I, [2020-03-30T12:00:39.544437 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/components/schemas/task.yml
I, [2020-03-30T12:00:39.544537 #22297]  INFO -- :  Use schema file: 	/Users/yukihirop/RubyProjects/example-600/oas_docs/src/components/requestBodies/task.yml
I, [2020-03-30T12:00:39.552871 #22297]  INFO -- : [Generate OAS docs from schema files] end

wait for single trap ...
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113181/d90ce7d5-1776-a9e4-3287-646d0081e63d.png)

## pahtsファイルの一覧が知りたい

PATHS_FILEを指定して書くと軽くなるといってもpathsファイルのyamlファイルのpathを調べるのがだるい。
その問題のために一覧を出すコマンドがあります。(ただ動作が遅いのでshellスクリプトで解決したがいいかもしれません。)

```bash
$ bundle exec rake routes:oas:paths_ls
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/action_mailbox/ingresses/postmark/inbound_email.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/action_mailbox/ingresses/sendgrid/inbound_email.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/action_mailbox/ingresses/mandrill/inbound_email.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/action_mailbox/ingresses/mailgun/inbound_email.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/action_mailbox/ingresses/relay/inbound_email.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/active_storage/disk.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/active_storage/representation.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/active_storage/blob.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/active_storage/direct_upload.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/user.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/api/v1/account.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/api/v2/custom_post.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/task.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/rails/conductor/action_mailbox/inbound_email.yml
/Users/yukihirop/RubyProjects/example-600/oas_docs/src/paths/rails/conductor/action_mailbox/reroute.yml
```

## cool-pecoを使った便利なスクリプト

pecoを便利につかうための[cool-peco](https://qiita.com/ryoppy/items/4819d0911bf937dba821)を使って便利スクリプトを書いておくといいです。

`api-editor`・ `api-ui` で pathsファイルを選択してEnterでSwaggerを開くことができるようになります。

#### pecoでAPIドキュメント編集

```bash
#pecoでAPIドキュメント編集
function peco-api-editor(){
  local unit_paths_file_path=$(find . -type f -name "*.yml" | grep paths | peco)
  if [ -n "$unit_paths_file_path" ]; then
    res="PATHS_FILE=$unit_paths_file_path bundle exec rake routes:oas:editor"
  fi
  _cool-peco-insert-command-line $res
}
alias api-editor=peco-api-editor
```

#### pecoでAPIドキュメント閲覧

```bash
#pecoでAPIドキュメント閲覧
function peco-api-ui(){
  local unit_paths_file_path=$(find . -type f -name "*.yml" | grep paths | peco)
  if [ -n "$unit_paths_file_path" ]; then
    res="PATHS_FILE=$unit_paths_file_path bundle exec rake routes:oas:ui"
  fi
  _cool-peco-insert-command-line $res
}
alias api-ui=peco-api-ui
```

## おわりに

次回は9月に進捗を報告します。
目標は `5個/週` です。