ドキュメント本文へスキップ
Ruby

ページネーション

ページ分割されるすべての一覧で、1 ページ、全ページ、または 1 アイテムずつ。

list、list_all、iterate

ページ分割されるすべての一覧には 3 つのメソッドがあります。list は 1 ページを取得して OpenEmail::Page を返します。list_all はすべてのページでカーソルをたどり、1 つの Array を返します。iterate は同じページを 1 アイテムずつたどり、各アイテムをブロックに yield するか、ブロックがなければ Enumerator を返します。3 つとも一覧のフィルター、limit:、cursor:、api_key: を受け取ります。

three_ways.rb
page = client.emails.list(status: "failed", limit: 50)page.items.each { |email| puts "#{email[:id]} #{email[:lastError]}" } failures = client.emails.list_all(status: "failed") client.emails.iterate(status: "failed") do |email|  puts email[:id]end puts failures.size, page.has_more?

名前空間に複数の一覧がある場合は、どこでも同じ 3 つの名前が、たどる一覧の名前を付けて繰り返されます。emails の list_events、list_all_events、iterate_events、webhooks の list_deliveries、list_all_deliveries、iterate_deliveries などです。

OpenEmail::Page

itemsArray<Hash>
このページの行。API の `data` エンベロープから取り出したもので、それぞれ Symbol キーの Hash です。ページに何もなければ空です。
has_more?Boolean
次のページがあるかどうか。疑問符のない `has_more` も同じ値を読みます。API が `hasMore` を送らない場合は、`next_cursor` があるときにちょうど true になります。
next_cursorString or nil
次のページのために `cursor:` として渡し返す値。最後のページでは nil。

ページは Ruby の Data オブジェクトなので、凍結されており、値で比較され、to_h で Hash に変換できます。

ブロックまたは Enumerator

ブロックを渡すと、iterate はその場ですべてのページをたどり、各アイテムをブロックに yield します。ブロックがなければ Enumerator を返し、消費されるまで何も取得しません。どちらの場合も、現在のページのアイテムがすべて yield されて初めて次のページを要求するため、早く止まる処理はリクエストも止めます。first(10) は 10 アイテムに必要な分のページだけを読み、find は一致した時点で止まり、ブロック内の break で走査が終わります。

enumerator.rb
latest = client.emails.iterate(status: "failed", limit: 100).first(10) invoice = client.emails.iterate(status: "failed").find do |email|  email.dig(:tags, :invoice) == "inv_2026_09_4192"end from_api = client.emails.iterate(status: "bounced").lazy.select { |email| email[:source] == "api" }.first(5) p latest.size, invoice&.fetch(:id), from_api.map { |email| email[:id] }

Enumerator に対して直接呼ぶ select、map、count のように、すべてのアイテムを必要とする Enumerable のメソッドは、list_all と同様に、戻る前にすべてのページを読みます。前に lazy を付ければ、メソッドをつなげながらも早く止められます。

Enumerator は消費されるたびに走査を最初からやり直すため、同じ Enumerator に first(10) を 2 回呼ぶと最初のページを 2 回取得します。もう一度必要なら、Enumerator ではなく結果を保持してください。

カーソルからの再開

カーソルは不透明な値です。最後に読んだページの next_cursor を保持し、cursor: として渡し返せば、後のリクエストや別のプロセスでもそこから続けられます。list_all と iterate も cursor: を受け取り、その後から走査を始めます。

resume.rb
first_page = client.emails.list(status: "failed", limit: 25)saved = first_page.next_cursor if saved  rest = client.emails.list_all(status: "failed", cursor: saved)  puts rest.sizeend

カーソルはそれを返した一覧とフィルターに属するため、同じフィルターと一緒に送ってください。一覧が位置を特定できないカーソルは invalid_cursor で拒否され、その場合はカーソルなしで最初からやり直します。

limit:

limit: は合計ではなく各ページのサイズです。list では返ってくる行数です。list_all と iterate では各リクエストが要求する件数なので、大きな値にすれば同じ行数を少ない往復で取得できます。各一覧には独自の範囲と既定値があり、多くは 1〜100 で、指定しなければ 25 です。範囲外の値は丸められるのではなく拒否されます。各一覧のページにその範囲が書かれています。

走査が止まるとき

  • ページの has_more? が false のとき。
  • ページに next_cursor がないとき。続きがあると言いながらカーソルを示さないページは、永遠にループしてしまうからです。
  • API が受け取ったばかりのカーソルをそのまま返してきたとき。理由は同じです。

各ページは GET なので、例外が送出される前に他の読み取りと同様に個別にリトライされます。リトライ後も残った失敗は list_all から送出され、それまでに取得したアイテムは破棄されます。iterate ではその時点で前のページのアイテムはすでに yield されているため、ブロックの処理を 2 回実行しても安全にするか、list でページを取得して各 next_cursor を保持し、2 回目の試行が 1 回目の止まった所から始められるようにしてください。

スレッドと下書き

threads.list と drafts.list、およびそれぞれの list_all と iterate は、カーソルではなく API の pageToken と nextPageToken でページ分割します。gem はこの違いを隠します。トークンは cursor: として渡し、next_cursor から読み取ってください。

page_token.rb
page = client.threads.list(folder: "inbox", limit: 50)later = client.threads.list(folder: "inbox", limit: 50, cursor: page.next_cursor) if page.has_more? p page.items.size, later&.items&.size

サーバーはページが満杯で返ってくるたびにトークンを出すため、結果的に最後だったページでも has_more? が true になることがあり、その場合は次の呼び出しがアイテムを返しません。

追加の情報を持つページ

いくつかの一覧は行以外の情報も返し、OpenEmail::Page の代わりに独自の Data オブジェクトを返します。

メソッド返すもの追加されるもの
addresses.listOpenEmail::AddressBookPageitems の代わりに addresses、さらに unrestricted と domains、および has_more? と next_cursor。
addresses.list_allOpenEmail::AddressBookaddresses にすべてのアドレスが入り、unrestricted と domains は最後のページが報告した値になります。Array ではなくアドレス帳全体を返す唯一の list_all です。addresses.iterate はアドレスだけを yield します。
contacts.list_peopleOpenEmail::PeoplePageseen。キーがメールに現れたアドレスを読めない場合は false です。list_all_people と iterate_people は人だけを返します。
temp_mail.list_messagesOpenEmail::TempMessagesPageexpires_at。受信箱の期限が切れる時刻です。list_all_messages と iterate_messages はメッセージだけを返します。
templates.list_sendsOpenEmail::TemplateSendsカーソルではなくページ番号でページ分割します:items、total、page、page_size。次のページは page: で要求します。
emails.send_batchOpenEmail::BatchResultページではありません:送信した各メッセージに 1 つずつの items と、sent と failed の件数。

API の Hash を返す一覧

一部の一覧はオフセット、ページ番号、または独自の数値カーソルでページ分割し、OpenEmail::Page ではなく、パース済みのボディを受け取ったまま、つまり data を持つ Hash として返します。list_all や iterate はないため、ページ分割は自分で行います。

メソッドページ分割の方法返ってくるもの
exports.listlimit: と offset:data、total、hasMore。
imports.list_failuresafter: と limit:data と、after: として渡し返す Integer の nextCursor。最後のページでは nil です。
subscriptions.list と subscriptions.list_domainslimit: と offset:data、total、counts、hasMore。
billing.list_invoicespage: と limit:data、total、page、limit、hasMore、metered。
offset_paging.rb
offset = 0 loop do  batch = client.subscriptions.list(status: "active", limit: 50, offset:)  batch[:data].each { |row| puts "#{row[:senderEmail]} #{row[:total]}" }   break unless batch[:hasMore]   offset += batch[:data].sizeend

languages.list、labels.list_colors、roles.list_permissions のように、ページ分割されない一覧はそのまま Array を返します。