Zur Dokumentation springen
Ruby

Paginierung

Eine Seite, alle Seiten oder ein Eintrag nach dem anderen, bei jeder Liste mit Seiten.

list, list_all und iterate

Jede Liste mit Seiten hat drei Methoden. list holt eine Seite und gibt eine OpenEmail::Page zurück. list_all folgt dem Cursor durch alle Seiten und gibt ein einziges Array zurück. iterate durchläuft dieselben Seiten Eintrag für Eintrag: Es übergibt jeden Eintrag an einen Block oder gibt einen Enumerator zurück, wenn Sie keinen Block angeben. Alle drei nehmen die Filter der Liste, limit:, cursor: und api_key: entgegen.

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?

Dieselben drei Namen wiederholen sich überall, wo ein Namespace mehr als eine Liste hat, benannt nach der Liste, die sie durchlaufen: list_events, list_all_events und iterate_events bei emails, list_deliveries, list_all_deliveries und iterate_deliveries bei webhooks und so weiter.

OpenEmail::Page

itemsArray<Hash>
Die Zeilen dieser Seite, aus dem `data`-Umschlag der API herausgelöst, jede ein Hash mit Symbol-Schlüsseln. Leer, wenn die Seite nichts enthält.
has_more?Boolean
Ob eine weitere Seite folgt. `has_more` ohne Fragezeichen liest denselben Wert. Sendet die API kein `hasMore`, ist es genau dann true, wenn es einen `next_cursor` gibt.
next_cursorString or nil
Was Sie für die nächste Seite als `cursor:` zurückgeben, und nil auf der letzten.

Eine Seite ist ein Ruby-Data-Objekt. Sie ist daher eingefroren, wird nach Wert verglichen und wird mit to_h zu einem Hash.

Ein Block oder ein Enumerator

Mit einem Block durchläuft iterate sofort alle Seiten und übergibt jeden Eintrag an den Block. Ohne Block gibt es einen Enumerator zurück und holt nichts, bis Sie ihn konsumieren. In beiden Fällen fordert es die nächste Seite erst an, wenn jeder Eintrag der aktuellen übergeben wurde. Alles, was früh aufhört, stoppt also auch die Anfragen: first(10) liest nur so viele Seiten, wie zehn Einträge brauchen, find stoppt beim Treffer, und break in einem Block beendet den Durchlauf.

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] }

Eine Enumerable-Methode, die jeden Eintrag braucht, etwa select, map oder count direkt auf dem Enumerator aufgerufen, liest jede Seite, bevor sie zurückkehrt, so wie list_all. Stellen Sie lazy voran, um sie zu verketten und trotzdem früh aufzuhören.

Ein Enumerator beginnt seinen Durchlauf bei jedem Konsumieren von vorn. Zweimal first(10) auf demselben Enumerator holt die erste Seite also zweimal. Behalten Sie das Ergebnis, nicht den Enumerator, wenn Sie es noch einmal brauchen.

Von einem Cursor aus fortsetzen

Ein Cursor ist opak. Behalten Sie den next_cursor der zuletzt gelesenen Seite und übergeben Sie ihn als cursor:, um dort weiterzumachen, in einer späteren Anfrage oder in einem anderen Prozess. list_all und iterate nehmen ebenfalls cursor: entgegen und beginnen ihren Durchlauf danach.

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

Ein Cursor gehört zu der Liste und den Filtern, aus denen er stammt, senden Sie also dieselben Filter mit. Einen Cursor, den die Liste nicht zuordnen kann, lehnt sie mit invalid_cursor ab, und dann hilft nur, ohne Cursor neu zu beginnen.

limit:

limit: ist die Größe jeder Seite, keine Gesamtzahl. Bei list ist es die Anzahl der zurückgegebenen Zeilen. Bei list_all und iterate ist es die Anzahl, die jede Anfrage anfordert, ein größerer Wert bedeutet also weniger Roundtrips für dieselben Zeilen. Jede Liste hat ihren eigenen Bereich und Standardwert, meist 1 bis 100 mit 25, wenn Sie nichts senden, und ein Wert außerhalb des Bereichs wird abgelehnt statt begrenzt. Die Seite jeder Liste nennt ihren Bereich.

Wann ein Durchlauf endet

  • Wenn eine Seite meldet, dass has_more? false ist.
  • Wenn eine Seite keinen next_cursor trägt, denn eine Seite, die mehr behauptet und dabei keinen Cursor nennt, würde endlos kreisen.
  • Wenn die API genau den Cursor zurückgibt, den sie gerade erhalten hat, aus demselben Grund.

Jede Seite ist ein GET und wird daher wie jeder Lesevorgang für sich wiederholt, bevor ein Fehler ausgelöst wird. Ein Fehlschlag, der die Wiederholungen übersteht, wird aus list_all heraus ausgelöst, und die bereits geholten Einträge werden verworfen. Bei iterate wurden die Einträge der früheren Seiten zu diesem Zeitpunkt schon übergeben. Sorgen Sie also dafür, dass der Block gefahrlos zweimal laufen kann, oder blättern Sie mit list und behalten Sie jeden next_cursor, damit ein zweiter Versuch dort beginnen kann, wo der erste aufgehört hat.

Threads und Entwürfe

threads.list und drafts.list blättern samt ihren list_all und iterate mit pageToken und nextPageToken der API statt mit einem Cursor. Das Gem verbirgt den Unterschied: Übergeben Sie das Token als cursor: und lesen Sie es aus 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

Der Server bietet ein Token an, wann immer eine Seite voll zurückkommt. has_more? kann also auf einer Seite true sein, die sich als die letzte herausstellt, und der nächste Aufruf gibt dann keine Einträge zurück.

Seiten, die mehr enthalten

Einige Listen antworten mit mehr als nur Zeilen und geben statt OpenEmail::Page ein eigenes Data-Objekt zurück.

MethodeGibt zurückWas sie ergänzt
addresses.listOpenEmail::AddressBookPageaddresses statt items, dazu unrestricted und domains, mit has_more? und next_cursor.
addresses.list_allOpenEmail::AddressBookJede Adresse in addresses, mit unrestricted und domains so, wie die letzte Seite sie gemeldet hat. Es ist das einzige list_all, das das ganze Adressbuch statt eines Arrays zurückgibt. addresses.iterate übergibt nur die Adressen.
contacts.list_peopleOpenEmail::PeoplePageseen, false, wenn der Schlüssel die in Mails gesehenen Adressen nicht lesen kann. list_all_people und iterate_people geben nur die Personen zurück.
temp_mail.list_messagesOpenEmail::TempMessagesPageexpires_at, wann der Posteingang abläuft. list_all_messages und iterate_messages geben nur die Nachrichten zurück.
templates.list_sendsOpenEmail::TemplateSendsNach Seitennummer statt nach Cursor geblättert: items, total, page und page_size. Fordern Sie die nächste Seite mit page: an.
emails.send_batchOpenEmail::BatchResultKeine Seite: items, ein Eintrag für jede gesendete Nachricht, mit den Zählern sent und failed.

Listen, die den Hash der API zurückgeben

Einige Listen blättern per Offset, per Seitennummer oder mit einem eigenen numerischen Cursor und geben den geparsten Body so zurück, wie er kam, als Hash mit data statt als OpenEmail::Page. Sie haben kein list_all und kein iterate, Sie blättern sie also selbst.

MethodeBlättert mitWas zurückkommt
exports.listlimit: und offset:data, total und hasMore.
imports.list_failuresafter: und limit:data und nextCursor, ein Integer, den Sie als after: zurückgeben und der auf der letzten Seite nil ist.
subscriptions.list und subscriptions.list_domainslimit: und offset:data, total, counts und hasMore.
billing.list_invoicespage: und limit:data, total, page, limit, hasMore und 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

Eine Liste ganz ohne Seiten, etwa languages.list, labels.list_colors oder roles.list_permissions, gibt direkt ein Array zurück.