狠狠撸
Submit Search
RailsでのREST API開発の知見共有
?
0 likes
?
3,260 views
Yusuke Kon
銀座Rails #40 2021/12/17 登壇資料
Read less
Read more
1 of 42
Download now
Download to read offline
More Related Content
RailsでのREST API開発の知見共有
1.
RailsでのRESTAPI開発の知見共有 株式会社UZUMAKICTO 今 佑介@kon_yu 銀座Rails#402021/12/17
2.
自己紹介 今 佑介@kon_yu 株式会社UZUMAKICTO 株式会社NoftyCTO 趣味 オンライン英会話 平日毎日レアジョブ 深夜ラジオ 最近のイチオシはマヂラブのANN クソアプリづくり
3.
株式会社UZUMAKIについて 今日のスポンサー株式会社UZUMAKI フリーランスのシニアエンジニア同士でチームを組んで仕事をしたら 仕事しやすんじゃないのという仮説のもと作られた会社 全員が調査?実装、仕様を決められれて、マネジメントスキルがあると仕事しやすいです
4.
今年のクソアプリアドベントカレンダー CO2センサーを使ったポモドーロタイマーを作って二酸化炭素濃度と生産性の相関を調べて みよう!
5.
础尘产颈别苍迟を使ってグラフ表示
6.
目次 OpenAPIを利用する要件 各ライブラリの特徴と要件を満たすか 各ライブラリの比較 まとめ
7.
OpenAPIを利用する要件 OpenAPIを使う要件を分解してみよう メンテナブルなAPI設計書をつくりたい モックサーバを使ってスキーマ駆動開発がしたい TypeScriptのAPIアクセス部分を自動生成したい
8.
メンテナブルなAPI設計書をつくりたい API設計書を自動生成してドキュメント作成コストを下げたい ソースコードとドキュメントの二重管理を避けたい 手動で作るとだんだんメンテナンスされなくなる この規模のサービスでもドキュメントない/メンテされてないの!?なんてことある よね? 参考:HowtouseOpenAPI3forAPIdeveloper
9.
モックサーバを使ってスキーマ駆動開発がしたい OpenAPIversion3に対応したメジャーなモックサーバ Prism 使い方はとても簡単 > prism mock
doc/openapi.yaml レスポンスはopenapi.yamlの各メソッドのexampleを返してくれる
10.
TypeScriptのAPIアクセス部分を自動生成したい OpenAPIから各種言語のフロントエンドの自動生成 openapi-generator Rubyも生成できるし、Swift,Kotlin,Dartも生成できる TypeScriptの生成も様々なタイプができるAngular,Aurelia,Axios,Fetch,Inversify, jQuery,Nestjs,Node,redux-query,Rxjs) 生成コマンド(axios対応のTypeScriptの場合) > openapi-generator-cli generate
-i ./YOUR_PATH/openapi.yaml -g typescript-axios -o openapi/types --additional-properties=modelPropertyNaming=camelCase,supportsES6=true
11.
自動生成されたコード例 async getShops() { state.isLoading
= true const { data, error }: any = await new ApiV1ShopApi( undefined, $config.baseURL, axios as AxiosInstance ) .apiV1ShopsGet(1, 1000) .catch((error) => { return { error } }) state.isLoading = false if (error) { state.error = error return } state.shops = data.shops },
12.
各ライブラリの特徴と要件を満たすか RailsでOpenAPIでググるとこの3つよく出る Grape committee-rails rspec-openapi ※ 以降生成されるOpenAPIのファイルopenapi.yamlを OpenAPI定義ファイル表記します
13.
Grape RailsのAPIモードが出る前まで、RailsでAPIといえばこれ Grape:https://github.com/ruby-grape/grape 現在ではあまり人気のないDSL形式でAPIを作成できる OpenAPIもRailsが動的に作成してくれる
14.
Grapeのメリット、デメリット メリット grape-entity レスポンスで返すモデルで表示させる属性を明示的にできる OpenAPIのレスポンスのコンポーネントを自動で作成してくれる grape-swagger OpenAPI定義ファイルを動的に生成、さらにSwaggerUIもついてくるオールインワ ン 先人の日本語情報が比較的多い
15.
Grapeのメリット、デメリット デメリット DSLのため学習コストがかかる スキーマを先に作って実装する駆動開発ができない grape-swaggerがOpenAPIのv2にしか対応されておらずv3のブランチがずっと本体にさ れていない
16.
Grapeが要件を満たすか メンテナブルなAPI設計書をつくりたい SwaggerUIもv2なので機能が少ない モックサーバを使ってスキーマ駆動開発がしたい PrismはOpenAPIv2にも対応 TypeScriptのAPIアクセス部分を自動生成したい 未確認、v2なのでだんだんメンテされなくなるだろう
17.
committee-rails committeeをrailsで組み込みやすくしてくれるgem committeeはOpenAPI定義ファイルは自分で書く必要があるが、 その定義通りのリクエスト?レスポンスをテストできる assert_schema_conform が便利 committee-rails:https://github.com/willnet/committee-rails
18.
committee-railsのメリット、デメリット メリット 純粋なスキーマ駆動開発ができる Prismでモックを動かせるのでRails側とフロント側で同時並行に実装できる 他2つと違ってRailsで入出力だけ作るなどからめ手が不要 OpenAPIの定義どおりにRailsを実装できたかテストできる
19.
committee-railsのメリット、デメリット デメリット OpenAPI定義ファイルを手作業で書かなければならい OpenAPI定義ファイルだけ先に作るので他2つよりも実装に不安がある 特に初期は項目の追加など手戻りが頻発する状態でフロントの担当に共有していいもの か悩ましい
20.
OpenAPI定義ファイルを手作業で書かなければならい問題は Spotlightstudioを使ってGUIで開発するとちょっと楽
21.
committee-railsが要件を満たすか メンテナブルなAPI設計書をつくりたい OpenAPIも最新のv3に対応 モックサーバを使ってスキーマ駆動開発がしたい PrismはOpenAPIv3に対応 TypeScriptのAPIアクセス部分を自動生成したい 正しいOpenAPIファイルなのできれいに生成する
22.
rspec-openapi Rspecのリクエストスペックを書けばOpenAPI定義ファイルを出力してくれる テスト駆動開発大好きな人に朗報 rspec-openapi:https://github.com/k0kubun/rspec-openapi
23.
rspec-openapiのメリット、デメリット メリット requestspecを書けば定義ファイルを作成してくれる 各APIのレスポンス例のexampleもテスト結果から作成してくれる(他2つにはない)
24.
requestspec例 it"hogehoge"doの箇所がOpenAPIのdescriptionにこの分が反映されるのでrspecのいつも の書き方をすると違和感が出やすいので注意 RSpec.describe 'Tables', type:
:request do describe '#index' do it 'テーブルの配列を取得する' do get '/tables', params: { page: '1', per: '10' }, headers: { authorization: 'k0kubun' } expect(response.status).to eq(200) end it 'does not return tables if unauthorized' do get '/tables' expect(response.status).to eq(401) end end # ... end
25.
生成されるOpenAPI定義ファイル例 openapi: 3.0.3 info: title: rspec-openapi paths: "/tables": get: summary:
index tags: - Table parameters: - name: page in: query schema: type: integer example: 1 - name: per in: query schema: type: integer example: 10 responses: '200': description: returns a list of tables content: application/json: schema: type: array items: type: object properties: id: type: integer name: type: string # ...
26.
rspec-openapiのメリット、デメリット デメリット 仕様を満たすOpenAPI定義ファイルを作るには、手動で対応するワークアラウンドが結 構ある ※ 今年ぶつかった問題なので急に具体的になります
27.
rspec-openapiのワークアラウンド ログイン必須の場合は各メソッドの定義に手動で追記する必要がある devise_token_authで認証用のgemを利用した場合 client,access_token,uidをヘッダにつける必要あり 各メソッドにつける paths: "/api/v1/shops": get: security: - client: [] access_token:
[] uid: []
28.
認証情報の定義 components: securitySchemes: client: type: apiKey description: ClientID in:
header name: client access_token: type: apiKey description: access-token in: header name: access-token uid: type: apiKey description: uid in: header name: uid
29.
rspec-openapiのワークアラウンド レスポンスがヘッダだけの場合不要な情報が付与されるので削除する必 要がある responses: '204': description: 商品カテゴリを更新 # これ以降を削除する content: '': schema: type:
string example: '' responses: '204': description: 商品カテゴリを更新
30.
rspec-openapiのワークアラウンド specを実行時にIDがインクリメントされるとパラメタが追加されてし まう letでidを指定してレコードを保存して実行すると、idがインクリメントされてparametersの 内容が増えてしまうため自動生成時に同じ入力パラメータが重複してエラーになる let(:category) { create(:category,
name: '名前') } IDを指定してやる let(:category) { create(:category, id:1, name: '名前') }
31.
rspec-openapiのワークアラウンド コンポーネントを自分で作らなければならない 自動生成されたもの responses: '200': description: 製品情報のリストを取得 content: application/json: schema: properties: products: type: array items: type:
object properties: id: type: integer name: type: string
32.
この状態だとコンポーネントを使わないとこのようなよろしくないクラス名になる /** * * @export * @interface
InlineResponse2006 */ export interface InlineResponse2006 { /** * * @type {number} * @memberof Shop */ id: number; ... }
33.
こういう意味の分かる名前のクラスを生成したい /** * * @export * @interface
Shop */ export interface Shop { /** * * @type {number} * @memberof Shop */ id: number; ... }
34.
そのためOpenAPI定義ファイルに responses: '200': description: お店のリスト取得する content: application/json: schema: properties: products: type: array items: "$ref":
"#/components/schemas/Shop"
35.
OpenAPI定義ファイルのコンポーネントの定義 components: schemas: Shop: nullable: true type: object properties: id: type:
integer name: type: string
36.
レスポンスをコンポーネントに移動したあと 新しいメソッドを追加し、OpenAPI定義ファイルを自動生成すると コンポーネントと、レスポンスのオブジェクトが2つ存在してしまう。
37.
つまりここうなってしまう responses: '200': description: お店のリストを取得 content: application/json: schema: properties: products: type: array items: "$ref":
"#/components/schemas/Shop" # せっかくコンポーネントを作ったのに下記の余分なものがついてしまう type: object properties: id: type: integer name: type: string
38.
OpenAPIgeneratorでTypeScriptを生成する際にエラーになるため都度消す必要がある。 ※ SwaggerUIやPrismを動かす分には先に書いてあるコンポーネントを利用するため気になら ない
39.
rspec-openapiが要件を満たすか メンテナブルなAPI設計書をつくりたい 最新のOpenAPIv3に対応するが、ワークアラウンドが多くAPIの本数が増える とどんどん辛くなる モックサーバを使ってスキーマ駆動開発がしたい PrismはOpenAPIv3に対応 TypeScriptのAPIアクセス部分を自動生成したい 特にコンポーネント周りのワークアラウンドを実施しないと、自動で命名された TypeScriptのクラスになってしまう
40.
まとめ 今回の要件要件 メンテナブルなAPI設計書をつくりたい モックサーバを使ってスキーマ駆動開発がしたい TypeScripのAPIアクセス部分を自動生成したい これらすべての要件を満たす のはcommittee-rails
41.
まとめ ただし開発の初期段階(1-3週間ぐらい)で、仕様が変わりやすい段階でcommittee-railsを使う と rspec-openapiで動作するRailsでOpenAPIを作成しつつ、 徐々に仕様が固まってAPIの本数が増えてきたらcommittee-railsに切り替えるのが良いのでな いか
42.
まとめ 実行時のOpenAPIの厳密さは右に行くほど適当な書き方だとエラーになる確率が上がる(体感) SwaggerUI>Prism>OpenapiGenerator そのためOpenAPIのファイルをコミットする場合は自動生成が通ってからコミットするのが コツ
Download