# frozen_string_literal: true module Fiken # An enumerable page of list results plus the pagination metadata Fiken # returns in `Fiken-Api-*` response headers. `#auto_paging_each` transparently # walks every remaining page. class Collection include Enumerable attr_reader :data, :page, :page_size, :page_count, :result_count def initialize(result, fetch_page:) @data = Array(result.body).map { |item| Object.new(item) } @page = header_int(result, "Fiken-Api-Page") @page_size = header_int(result, "Fiken-Api-Page-Size") @page_count = header_int(result, "Fiken-Api-Page-Count") @result_count = header_int(result, "Fiken-Api-Result-Count") @fetch_page = fetch_page end def each(&) @data.each(&) end # Iterates every element across all remaining pages, fetching them lazily. def auto_paging_each(&block) return enum_for(:auto_paging_each) unless block_given? current = self loop do current.each(&block) break if current.last_page? current = current.next_page end end def last_page? return true if page.nil? || page_count.nil? page >= page_count - 1 end def next_page raise Error, "no more pages" if last_page? @fetch_page.call(page + 1) end private def header_int(result, name) value = result.headers[name] value && !value.to_s.empty? ? value.to_i : nil end end end