ohata です
2月末と3月頭で[RailsGirls]と[TokyoGirls.rb]にスポンサー枠で参加させてもらいました
コミュニティのモチベーションなどいろいろ学びになる事が多かったので、 これからもコミュニティには積極的に参加していきたいなーと思います。
最近のプロジェクトでAPIを作る機会があったので、その時の過程について 書こうと思います・
REST API or GraphQL?
GraphQLを業務で使ったこともないので候補として検討しようと思いました。 色々条件を検討した結果、今回はRESTでいく事にしました。
REST APIに決めた条件
- 今回は使われる箇所が限定的である (呼び出し側が特定されている)
- 要件がそこまで柔軟に対応する必要がない
- キャッシュ対応が既存の仕組みで作りやすい
OpenAPI3.0
[REST API]経験者も多いのでそれなりに作れてしまう箇所もありますが、 苦になるのがドキュメントのメンテだったりします。
[REST API]を運用する上で、どちらかのアプローチで解決したいなと思いました。
- コードからAPIドキュメントが自動的に作られたら良い (GraphQLみたいな)
- ドキュメント作成だけを考えたら良いけど ,気づかないところで変更されて 利用側でエラーが発生する可能性が高い
- ドキュメントからコードを作成する
- コードの内容は結構変わっていくので、ドキュメントとのdiffがいつか必要になりそう
[REST API]で動的に項目を追加、削除(filterの対応)したりするのはメンテコストが大きいので [2]のアプローチの方が良いとは思っています。
なんでドキュメント作成をつらいと感じるのか? (個人的見解)
- 何かプロジェクト価値観的にいまいち
- メンテするのにテンション下がる (個人の問題)
ドキュメントをコードと同じ扱いでかければ、メンテしていけると思うので
[ドキュメントに沿って、specが実行できればテスト書いてるイメージでメンテできる]
で行こうと思います
OpenAPI3.0
基本的にgem(committee,apirov)で対応しようと思います。 OpenApi3.0の対応状況見て [Swagger2.0] で行こうと思ったのですが
開発中に こちらのブログをみて、 OpenAPI3.0を採用しようと決めました (タイミングが良すぎた^^)
変更点などは、いくつかあるのですが個人的には、以下の変更は(components)はjsっぽくて 何か親しみを感じました (実装上そんな関係ない...)
Swagger2.0
"definitions" : {
OpenAPI3.0
"components": { "schemas": {
あとちょっと気になったのですが、required を properties と分けて記載できるように なったためか、required指定が名称になっていました。
Swagger2.0
"properties": { "name": { "type": "string", "required": true }, "email": { "type": "string", "required": true },
OpenAPI3.0
"properties": { "name": { "type": "string", "required": name ## "required": true と描きたいかも }, "email": { "type": "string", "required": email },
こうも書ける
"required": [ "name", "email" ], "properties": { "name": { "type": "string", }, "email": { "type": "string", },
Swagger2.0 -> OpenAPI3.0への移行
Schemaのアップデート
定義を確認しながらやっても良いのですが、サンプルなどがあった方が捗るので
こちらのサイトでコンバートしました
Swaggerで確認
Swagger のeditor部分にスキーマをpasetすれば 右側のプレビューで確認できます。 ドキュメント問題はとりあえずこれで良いかと思います
gemの導入
gem 'committee' gem 'committee-rails'
comitteeの利用方法
require 'rails_helper' RSpec.describe 'Orders', type: :request do include Committee::Rails::Test::Methods def committee_options @committee_options ||= { schema_path: Rails.root.join('docs', 'swagger.yml').to_s } end describe 'スキーマの確認' do describe 'GET /api/hoge/:id' do let(:id) { 1 } it 'レスポンスがAPI定義と一致する' do get "/api/hoge/#{id}" assert_schema_conform end end end end
アップデート前(Swagger2.0)
def committee_schema @committee_schema ||= begin driver = Committee::Drivers::OpenAPI2.new schema = JSON.parse(File.read(schema_path)) driver.parse(schema) end end def schema_path Rails.root.join('docs', 'swagger.json') end
Swagger2.0 の実装時はデフォルトのスキーマパスをoverrideしてあげたりしなければ行けなかったので こちらの方がシンプルな感じがしました
テストの実行
bundle exec rspec spec/requests/api/hoge_spec.rb
format対応について
全てに対応はしてないと思うのですが、基本的に使うformatについては特に問題ないと思いました。
まとめ
今回導入時にgemが対応してくれたのでコミッターの方には本当感謝です
次回大きめのプロジェクトやる時は GraphQLの方も導入したいと思います。
( browser -> GraphQL -> (DB, APIなど) みたいな構成イメージ )