Class: Retab::PaginatedList

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/retab/paginated_list.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data: [], list_metadata: {}, last_response: nil, fetch_next: nil) ⇒ PaginatedList

Returns a new instance of PaginatedList.

Parameters:

  • data (Array) (defaults to: [])
  • list_metadata (Hash) (defaults to: {})

    envelope with ‘before` / `after` cursors

  • last_response (Retab::Types::ApiResponse, nil) (defaults to: nil)
  • fetch_next (#call, nil) (defaults to: nil)

    closure that takes the next cursor and returns the next page; ‘nil` for terminal pages or rehydrated fixtures



32
33
34
35
36
37
# File 'lib/retab/paginated_list.rb', line 32

def initialize(data: [], list_metadata: {}, last_response: nil, fetch_next: nil)
  @data = data || []
  @list_metadata =  || {}
  @last_response = last_response
  @fetch_next = fetch_next
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



25
26
27
# File 'lib/retab/paginated_list.rb', line 25

def data
  @data
end

#last_responseObject (readonly)

Returns the value of attribute last_response.



25
26
27
# File 'lib/retab/paginated_list.rb', line 25

def last_response
  @last_response
end

#list_metadataObject (readonly)

Returns the value of attribute list_metadata.



25
26
27
# File 'lib/retab/paginated_list.rb', line 25

def 
  @list_metadata
end

Class Method Details

.from_response(response, model: nil, filters: {}, fetch_next: nil) ⇒ Object

Construct a PaginatedList from an HTTP response with ‘[…], list_metadata: {…}`.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/retab/paginated_list.rb', line 68

def self.from_response(response, model: nil, filters: {}, fetch_next: nil)
  _ = filters
  body = response.respond_to?(:body) ? response.body : response
  parsed = body.is_a?(String) ? JSON.parse(body) : (body || {})
  raw_items = parsed["data"] || parsed[:data] || []
  items = raw_items.map { |item| model ? model.new(item) : item }
  meta = parsed["list_metadata"] || parsed[:list_metadata] || {}
  api_response = if response.respond_to?(:code)
    Types::ApiResponse.new(
      http_status: response.code.to_i,
      http_headers: response.respond_to?(:each_header) ? response.each_header.to_h : {},
      request_id: response.respond_to?(:[]) ? response["x-request-id"] : nil
    )
  end

  new(data: items, list_metadata: meta, last_response: api_response, fetch_next: fetch_next)
end

Instance Method Details

#eachObject

Iterate every page lazily. Each page’s ‘data` is yielded item-by-item; when the cursor advances, the captured closure is invoked to fetch the next page and iteration continues. Terminal pages stop after the last in-memory item.



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/retab/paginated_list.rb', line 43

def each
  return enum_for(:each) unless block_given?
  page = self
  loop do
    page.data.each { |item| yield item }
    break unless page.has_next? && @fetch_next
    cursor = page.[:after] || page.["after"]
    page = @fetch_next.call(cursor)
    break unless page
  end
end

#has_next?Boolean

Returns:

  • (Boolean)


55
56
57
58
# File 'lib/retab/paginated_list.rb', line 55

def has_next?
  cursor = @list_metadata.is_a?(Hash) ? (@list_metadata[:after] || @list_metadata["after"]) : nil
  !cursor.nil? && !cursor.to_s.empty?
end

#next_pageObject



60
61
62
63
64
# File 'lib/retab/paginated_list.rb', line 60

def next_page
  return nil unless has_next? && @fetch_next
  cursor = @list_metadata[:after] || @list_metadata["after"]
  @fetch_next.call(cursor)
end