Class: Gapic::Rest::PagedEnumerable

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/gapic/rest/paged_enumerable.rb

Overview

A class to provide the Enumerable interface to the response of a REST paginated method. PagedEnumerable assumes response message holds a list of resources and the token to the next page.

PagedEnumerable provides the enumerations over the resource data, and also provides the enumerations over the pages themselves.

Examples:

normal iteration over resources.

paged_enumerable.each { |resource| puts resource }

per-page iteration.

paged_enumerable.each_page { |page| puts page }

Enumerable over pages.

paged_enumerable.each_page do |page|
  page.each { |resource| puts resource }
end

more exact operations over pages.

while some_condition()
  page = paged_enumerable.page
  do_something(page)
  break if paged_enumerable.next_page?
  paged_enumerable.next_page
end

Defined Under Namespace

Classes: Page

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#pagePage (readonly)

Returns The current page object.

Returns:

  • (Page)

    The current page object.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/gapic/rest/paged_enumerable.rb', line 46

class PagedEnumerable
  include Enumerable

  attr_reader :page

  ##
  # @private
  # @param service_stub [Object] The REST service_stub with the baseline implementation for the wrapped method.
  # @param method_name [Symbol] The REST method name that is being wrapped.
  # @param request [Object] The request object.
  # @param response [Object] The response object.
  # @param options [Gapic::CallOptions] The options for making the RPC call.
  # @param format_resource [Proc] A Proc object to format the resource object. The Proc should accept response as an
  #   argument, and return a formatted resource object. Optional.
  #
  def initialize service_stub, method_name, resource_field_name, request, response, options, format_resource: nil
    @service_stub = service_stub
    @method_name = method_name
    @resource_field_name = resource_field_name
    @request = request
    @response = response
    @options = options
    @format_resource = format_resource

    @page = Page.new response, resource_field_name, format_resource: @format_resource
  end

  ##
  # Iterate over the individual resources, automatically requesting new pages as needed.
  #
  # @yield [Object] Gives the resource objects in the stream.
  #
  # @return [Enumerator] if no block is provided
  #
  def each &block
    return enum_for :each unless block_given?

    each_page do |page|
      page.each(&block)
    end
  end

  ##
  # Iterate over the pages.
  #
  # @yield [Page] Gives the pages in the stream.
  #
  # @return [Enumerator] if no block is provided
  #
  def each_page
    return enum_for :each_page unless block_given?

    loop do
      break if @page.nil?
      yield @page
      next_page!
    end
  end

  ##
  # True if there is at least one more page of results.
  #
  # @return [Boolean]
  #
  def next_page?
    !next_page_token.nil? && !next_page_token.empty?
  end

  ##
  # Load the next page and set it as the current page.
  # If there is no next page, sets nil as a current page.
  #
  # @return [Page, nil] the new page object.
  #
  def next_page!
    unless next_page?
      @page = nil
      return @page
    end

    next_request = @request.dup
    next_request.page_token = @page.next_page_token

    @response = @service_stub.send @method_name, next_request, @options
    @page = Page.new @response, @resource_field_name, format_resource: @format_resource
  end
  alias next_page next_page!

  ##
  # The page token to be used for the next RPC call, or the empty string if there is no next page.
  # nil if the iteration is complete.
  #
  # @return [String, nil]
  #
  def next_page_token
    @page&.next_page_token
  end

  ##
  # The current response object, for the current page.
  # nil if the iteration is complete.
  #
  # @return [Object, nil]
  #
  def response
    @page&.response
  end

  ##
  # A class to represent a page in a PagedEnumerable. This also implements Enumerable, so it can iterate over the
  # resource elements.
  #
  # @attribute [r] response
  #   @return [Object] the response object for the page.
  class Page
    include Enumerable
    attr_reader :response

    ##
    # @private
    # @param response [Object] The response object for the page.
    # @param resource_field [String] The name of the field in response which holds the resources.
    # @param format_resource [Proc, nil] A Proc object to format the resource object. Default nil (no formatting).
    # The Proc should accept response as an argument, and return a formatted resource object. Optional.
    #
    def initialize response, resource_field, format_resource: nil
      @response = response
      @resource_field = resource_field
      @format_resource = format_resource
    end

    ##
    # Iterate over the resources.
    #
    # @yield [Object] Gives the resource objects in the page.
    #
    # @return [Enumerator] if no block is provided
    #
    def each
      return enum_for :each unless block_given?

      # We trust that the field exists and is an Enumerable
      resources.each do |resource|
        resource = @format_resource.call resource if @format_resource
        yield resource
      end
    end

    ##
    # The page token to be used for the next RPC call, or the empty string if there is no next page.
    #
    # @return [String]
    #
    def next_page_token
      @response.next_page_token
    end

    ##
    # Whether the next_page_token exists and is not empty
    #
    # @return [Boolean]
    #
    def next_page_token?
      !next_page_token.empty?
    end

    ##
    # Resources in this page presented as an array.
    # When the iterable is a protobuf map, the `.each |item|` gives just the keys
    # to iterate like a normal hash it should be converted to an array first
    #
    # @return [Array]
    #
    def resources
      @resources ||= @response[@resource_field].to_a
    end
  end
end

Instance Method Details

#each {|Object| ... } ⇒ Enumerator

Iterate over the individual resources, automatically requesting new pages as needed.

Yields:

  • (Object)

    Gives the resource objects in the stream.

Returns:

  • (Enumerator)

    if no block is provided



80
81
82
83
84
85
86
# File 'lib/gapic/rest/paged_enumerable.rb', line 80

def each &block
  return enum_for :each unless block_given?

  each_page do |page|
    page.each(&block)
  end
end

#each_page {|Page| ... } ⇒ Enumerator

Iterate over the pages.

Yields:

  • (Page)

    Gives the pages in the stream.

Returns:

  • (Enumerator)

    if no block is provided



95
96
97
98
99
100
101
102
103
# File 'lib/gapic/rest/paged_enumerable.rb', line 95

def each_page
  return enum_for :each_page unless block_given?

  loop do
    break if @page.nil?
    yield @page
    next_page!
  end
end

#next_page!Page? Also known as: next_page

Load the next page and set it as the current page. If there is no next page, sets nil as a current page.

Returns:

  • (Page, nil)

    the new page object.



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/gapic/rest/paged_enumerable.rb', line 120

def next_page!
  unless next_page?
    @page = nil
    return @page
  end

  next_request = @request.dup
  next_request.page_token = @page.next_page_token

  @response = @service_stub.send @method_name, next_request, @options
  @page = Page.new @response, @resource_field_name, format_resource: @format_resource
end

#next_page?Boolean

True if there is at least one more page of results.

Returns:

  • (Boolean)


110
111
112
# File 'lib/gapic/rest/paged_enumerable.rb', line 110

def next_page?
  !next_page_token.nil? && !next_page_token.empty?
end

#next_page_tokenString?

The page token to be used for the next RPC call, or the empty string if there is no next page. nil if the iteration is complete.

Returns:

  • (String, nil)


140
141
142
# File 'lib/gapic/rest/paged_enumerable.rb', line 140

def next_page_token
  @page&.next_page_token
end

#responseObject?

The current response object, for the current page. nil if the iteration is complete.

Returns:

  • (Object, nil)


150
151
152
# File 'lib/gapic/rest/paged_enumerable.rb', line 150

def response
  @page&.response
end