my_api_client v0.15.0 をリリースしました🚀
その前に v0.14.0
もリリースしているのですが、こちらはリファクタリングと Integration Test の実装だけで新機能はありませんでした。
差分が +2,799 -1,246
もあるので中身は結構書き換わっています。
Release v0.14.0 · ryz310/my_api_client · GitHub
Integration Test では Ruby on Jets を使って AWS Lambda でサーバーを建てて、CI でのテストで my_api_client
を使って実際に HTTP リクエストが成功することを確認しているので、デグレの心配が随分と緩和されました 😌
新機能: Pagination API のサポート
ここからは v0.15.0
の話になります。
Release v0.15.0 · ryz310/my_api_client · GitHub
v0.15.0
のメイン機能が Pagination API のサポートになります。JSON:API というしっかりとした仕様もあるようですが、 my_api_client
ではそこまで厳密な仕様に則っている訳ではなく、レスポンスに含まれる URL を認識して enumerable に HTTP リクエストを実行する、というざっくりした機能になります。
レスポンスヘッダの Link
などで次のページの URL を返すケースもあるようですが、そちらは現時点では未対応です 🙏
Pagination API という単語は Django REST Framework の Pagination 機能の説明で出てきます。
要するに一度のリクエストで結果を全件取得させるのではなく、一定の件数を返却し、続きを取得できる Link を一緒に返却する API のことですね。
Request:
GET https://api.example.org/accounts/?page=4
Response:
HTTP 200 OK { "count": 1023 "next": "https://api.example.org/accounts/?page=5", "previous": "https://api.example.org/accounts/?page=3", "results": [ … ] }
使い方
my_api_client
での使い方は以下のようになります。
class MyPaginationApiClient < ApplicationApiClient endpoint 'https://example.com/v1' # GET pagination?page=1 def pagination pageable_get 'pagination', paging: '$.links.next', headers: headers, query: { page: 1 } end private def headers { 'Content-Type': 'application/json;charset=UTF-8' } end end
通常であれば #get
を使って HTTP リクエストを実行させるのですが、ここでは #pageable_get
というメソッドを使用しています。 #pageable_get
だと長いので #pget
というエイリアスも用意しています。
また、 paging
というキーワード引数も新たに出てきました。 paging
ではレスポンスのどの部分に次のページの URL が含まれるかを JSONPath expression で指定します。
以下のような JSON であれば、 $.links.next
という JSONPath expression は "https://example.com/pagination?page=3"
を取得します。
{ "links": { "next": "https://example.com/pagination?page=3", "previous": "https://example.com/pagination?page=1", }, "page": 2 }
作成した API Client は以下のように使用できます。
api_clinet = MyPaginationApiClient.new api_clinet.pagination.each do |response| # Do something. end p = api_clinet.pagination p.next # => 1st page result p.next # => 2nd page result p.next # => 3rd page result
結果は Enumerator::Lazy
で返却される
#pageable_get
は Enumerator::Lazy
を返却するので、 Enumerable
で定義されているメソッドは一通り利用可能です。
Enumerator
で返してしまうと #take
で 100 ページ目まで結果を取得するような処理を記述したときに、
- 100 ページ分の HTTP リクエストを実行
- 結果を
#each
で回す
という動きになり、 100 回分の HTTP リクエストが完了するまで次の処理に移ることができません。
Enumerator::Lazy
であれば、
という動きになってくれます。便利ですね ✨
Enumerator
と Enumerator::Lazy
の違いは以下の記事が参考になると思います。