jomz-google-api-client 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. data/CHANGELOG.md +144 -0
  2. data/CONTRIBUTING.md +32 -0
  3. data/Gemfile +41 -0
  4. data/LICENSE +202 -0
  5. data/README.md +192 -0
  6. data/Rakefile +46 -0
  7. data/lib/cacerts.pem +2183 -0
  8. data/lib/compat/multi_json.rb +16 -0
  9. data/lib/google/api_client.rb +672 -0
  10. data/lib/google/api_client/auth/compute_service_account.rb +28 -0
  11. data/lib/google/api_client/auth/file_storage.rb +87 -0
  12. data/lib/google/api_client/auth/installed_app.rb +122 -0
  13. data/lib/google/api_client/auth/jwt_asserter.rb +126 -0
  14. data/lib/google/api_client/auth/key_utils.rb +93 -0
  15. data/lib/google/api_client/auth/pkcs12.rb +41 -0
  16. data/lib/google/api_client/batch.rb +323 -0
  17. data/lib/google/api_client/client_secrets.rb +176 -0
  18. data/lib/google/api_client/discovery.rb +19 -0
  19. data/lib/google/api_client/discovery/api.rb +300 -0
  20. data/lib/google/api_client/discovery/media.rb +77 -0
  21. data/lib/google/api_client/discovery/method.rb +363 -0
  22. data/lib/google/api_client/discovery/resource.rb +156 -0
  23. data/lib/google/api_client/discovery/schema.rb +121 -0
  24. data/lib/google/api_client/environment.rb +42 -0
  25. data/lib/google/api_client/errors.rb +60 -0
  26. data/lib/google/api_client/gzip.rb +28 -0
  27. data/lib/google/api_client/logging.rb +32 -0
  28. data/lib/google/api_client/media.rb +259 -0
  29. data/lib/google/api_client/railtie.rb +16 -0
  30. data/lib/google/api_client/reference.rb +27 -0
  31. data/lib/google/api_client/request.rb +351 -0
  32. data/lib/google/api_client/result.rb +253 -0
  33. data/lib/google/api_client/service.rb +233 -0
  34. data/lib/google/api_client/service/batch.rb +103 -0
  35. data/lib/google/api_client/service/request.rb +144 -0
  36. data/lib/google/api_client/service/resource.rb +40 -0
  37. data/lib/google/api_client/service/result.rb +162 -0
  38. data/lib/google/api_client/service/simple_file_store.rb +151 -0
  39. data/lib/google/api_client/service/stub_generator.rb +59 -0
  40. data/lib/google/api_client/service_account.rb +18 -0
  41. data/lib/google/api_client/version.rb +31 -0
  42. data/lib/google/inflection.rb +28 -0
  43. data/spec/fixtures/files/privatekey.p12 +0 -0
  44. data/spec/fixtures/files/sample.txt +33 -0
  45. data/spec/fixtures/files/secret.pem +19 -0
  46. data/spec/google/api_client/batch_spec.rb +249 -0
  47. data/spec/google/api_client/discovery_spec.rb +652 -0
  48. data/spec/google/api_client/gzip_spec.rb +86 -0
  49. data/spec/google/api_client/media_spec.rb +179 -0
  50. data/spec/google/api_client/request_spec.rb +30 -0
  51. data/spec/google/api_client/result_spec.rb +203 -0
  52. data/spec/google/api_client/service_account_spec.rb +164 -0
  53. data/spec/google/api_client/service_spec.rb +586 -0
  54. data/spec/google/api_client/simple_file_store_spec.rb +137 -0
  55. data/spec/google/api_client_spec.rb +253 -0
  56. data/spec/spec_helper.rb +56 -0
  57. data/tasks/gem.rake +97 -0
  58. data/tasks/git.rake +45 -0
  59. data/tasks/metrics.rake +22 -0
  60. data/tasks/spec.rake +57 -0
  61. data/tasks/wiki.rake +82 -0
  62. data/tasks/yard.rake +29 -0
  63. metadata +309 -0
@@ -0,0 +1,16 @@
1
+ require 'google/api_client/logging'
2
+
3
+ module Google
4
+ class APIClient
5
+
6
+ ##
7
+ # Optional support class for Rails. Currently replaces the built-in logger
8
+ # with Rails' application log.
9
+ #
10
+ class Railtie < Rails::Railtie
11
+ initializer 'google-api-client' do |app|
12
+ Google::APIClient.logger = Rails.logger
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'google/api_client/request'
16
+
17
+ module Google
18
+ class APIClient
19
+ ##
20
+ # Subclass of Request for backwards compatibility with pre-0.5.0 versions of the library
21
+ #
22
+ # @deprecated
23
+ # use {Google::APIClient::Request} instead
24
+ class Reference < Request
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,351 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'faraday'
16
+ require 'faraday/request/multipart'
17
+ require 'multi_json'
18
+ require 'compat/multi_json'
19
+ require 'addressable/uri'
20
+ require 'stringio'
21
+ require 'google/api_client/discovery'
22
+ require 'google/api_client/logging'
23
+
24
+ module Google
25
+ class APIClient
26
+
27
+ ##
28
+ # Represents an API request.
29
+ class Request
30
+ include Google::APIClient::Logging
31
+
32
+ MULTIPART_BOUNDARY = "-----------RubyApiMultipartPost".freeze
33
+
34
+ # @return [Hash] Request parameters
35
+ attr_reader :parameters
36
+ # @return [Hash] Additional HTTP headers
37
+ attr_reader :headers
38
+ # @return [Google::APIClient::Method] API method to invoke
39
+ attr_reader :api_method
40
+ # @return [Google::APIClient::UploadIO] File to upload
41
+ attr_accessor :media
42
+ # @return [#generated_authenticated_request] User credentials
43
+ attr_accessor :authorization
44
+ # @return [TrueClass,FalseClass] True if request should include credentials
45
+ attr_accessor :authenticated
46
+ # @return [#read, #to_str] Request body
47
+ attr_accessor :body
48
+
49
+ ##
50
+ # Build a request
51
+ #
52
+ # @param [Hash] options
53
+ # @option options [Hash, Array] :parameters
54
+ # Request parameters for the API method.
55
+ # @option options [Google::APIClient::Method] :api_method
56
+ # API method to invoke. Either :api_method or :uri must be specified
57
+ # @option options [TrueClass, FalseClass] :authenticated
58
+ # True if request should include credentials. Implicitly true if
59
+ # unspecified and :authorization present
60
+ # @option options [#generate_signed_request] :authorization
61
+ # OAuth credentials
62
+ # @option options [Google::APIClient::UploadIO] :media
63
+ # File to upload, if media upload request
64
+ # @option options [#to_json, #to_hash] :body_object
65
+ # Main body of the API request. Typically hash or object that can
66
+ # be serialized to JSON
67
+ # @option options [#read, #to_str] :body
68
+ # Raw body to send in POST/PUT requests
69
+ # @option options [String, Addressable::URI] :uri
70
+ # URI to request. Either :api_method or :uri must be specified
71
+ # @option options [String, Symbol] :http_method
72
+ # HTTP method when requesting a URI
73
+ def initialize(options={})
74
+ @parameters = Faraday::Utils::ParamsHash.new
75
+ @headers = Faraday::Utils::Headers.new
76
+
77
+ self.parameters.merge!(options[:parameters]) unless options[:parameters].nil?
78
+ self.headers.merge!(options[:headers]) unless options[:headers].nil?
79
+ self.api_method = options[:api_method]
80
+ self.authenticated = options[:authenticated]
81
+ self.authorization = options[:authorization]
82
+
83
+ # These parameters are handled differently because they're not
84
+ # parameters to the API method, but rather to the API system.
85
+ self.parameters['key'] ||= options[:key] if options[:key]
86
+ self.parameters['userIp'] ||= options[:user_ip] if options[:user_ip]
87
+
88
+ if options[:media]
89
+ self.initialize_media_upload(options)
90
+ elsif options[:body]
91
+ self.body = options[:body]
92
+ elsif options[:body_object]
93
+ self.headers['Content-Type'] ||= 'application/json'
94
+ self.body = serialize_body(options[:body_object])
95
+ else
96
+ self.body = ''
97
+ end
98
+
99
+ unless self.api_method
100
+ self.http_method = options[:http_method] || 'GET'
101
+ self.uri = options[:uri]
102
+ end
103
+ end
104
+
105
+ # @!attribute [r] upload_type
106
+ # @return [String] protocol used for upload
107
+ def upload_type
108
+ return self.parameters['uploadType'] || self.parameters['upload_type']
109
+ end
110
+
111
+ # @!attribute http_method
112
+ # @return [Symbol] HTTP method if invoking a URI
113
+ def http_method
114
+ return @http_method ||= self.api_method.http_method.to_s.downcase.to_sym
115
+ end
116
+
117
+ def http_method=(new_http_method)
118
+ if new_http_method.kind_of?(Symbol)
119
+ @http_method = new_http_method.to_s.downcase.to_sym
120
+ elsif new_http_method.respond_to?(:to_str)
121
+ @http_method = new_http_method.to_s.downcase.to_sym
122
+ else
123
+ raise TypeError,
124
+ "Expected String or Symbol, got #{new_http_method.class}."
125
+ end
126
+ end
127
+
128
+ def api_method=(new_api_method)
129
+ if new_api_method.nil? || new_api_method.kind_of?(Google::APIClient::Method)
130
+ @api_method = new_api_method
131
+ else
132
+ raise TypeError,
133
+ "Expected Google::APIClient::Method, got #{new_api_method.class}."
134
+ end
135
+ end
136
+
137
+ # @!attribute uri
138
+ # @return [Addressable::URI] URI to send request
139
+ def uri
140
+ return @uri ||= self.api_method.generate_uri(self.parameters)
141
+ end
142
+
143
+ def uri=(new_uri)
144
+ @uri = Addressable::URI.parse(new_uri)
145
+ @parameters.update(@uri.query_values) unless @uri.query_values.nil?
146
+ end
147
+
148
+
149
+ # Transmits the request with the given connection
150
+ #
151
+ # @api private
152
+ #
153
+ # @param [Faraday::Connection] connection
154
+ # the connection to transmit with
155
+ # @param [TrueValue,FalseValue] is_retry
156
+ # True if request has been previous sent
157
+ #
158
+ # @return [Google::APIClient::Result]
159
+ # result of API request
160
+ def send(connection, is_retry = false)
161
+ self.body.rewind if is_retry && self.body.respond_to?(:rewind)
162
+ env = self.to_env(connection)
163
+ logger.debug { "#{self.class} Sending API request #{env[:method]} #{env[:url].to_s} #{env[:request_headers]}" }
164
+ http_response = connection.app.call(env)
165
+ result = self.process_http_response(http_response)
166
+
167
+ logger.debug { "#{self.class} Result: #{result.status} #{result.headers}" }
168
+
169
+ # Resumamble slightly different than other upload protocols in that it requires at least
170
+ # 2 requests.
171
+ if result.status == 200 && self.upload_type == 'resumable'
172
+ upload = result.resumable_upload
173
+ unless upload.complete?
174
+ logger.debug { "#{self.class} Sending upload body" }
175
+ result = upload.send(connection)
176
+ end
177
+ end
178
+ return result
179
+ end
180
+
181
+ # Convert to an HTTP request. Returns components in order of method, URI,
182
+ # request headers, and body
183
+ #
184
+ # @api private
185
+ #
186
+ # @return [Array<(Symbol, Addressable::URI, Hash, [#read,#to_str])>]
187
+ def to_http_request
188
+ request = (
189
+ if self.api_method
190
+ self.api_method.generate_request(self.parameters, self.body, self.headers)
191
+ elsif self.uri
192
+ unless self.parameters.empty?
193
+ self.uri.query = Addressable::URI.form_encode(self.parameters)
194
+ end
195
+ [self.http_method, self.uri.to_s, self.headers, self.body]
196
+ end)
197
+ return request
198
+ end
199
+
200
+ ##
201
+ # Hashified verison of the API request
202
+ #
203
+ # @return [Hash]
204
+ def to_hash
205
+ options = {}
206
+ if self.api_method
207
+ options[:api_method] = self.api_method
208
+ options[:parameters] = self.parameters
209
+ else
210
+ options[:http_method] = self.http_method
211
+ options[:uri] = self.uri
212
+ end
213
+ options[:headers] = self.headers
214
+ options[:body] = self.body
215
+ options[:media] = self.media
216
+ unless self.authorization.nil?
217
+ options[:authorization] = self.authorization
218
+ end
219
+ return options
220
+ end
221
+
222
+ ##
223
+ # Prepares the request for execution, building a hash of parts
224
+ # suitable for sending to Faraday::Connection.
225
+ #
226
+ # @api private
227
+ #
228
+ # @param [Faraday::Connection] connection
229
+ # Connection for building the request
230
+ #
231
+ # @return [Hash]
232
+ # Encoded request
233
+ def to_env(connection)
234
+ method, uri, headers, body = self.to_http_request
235
+ http_request = connection.build_request(method) do |req|
236
+ req.url(uri.to_s)
237
+ req.headers.update(headers)
238
+ req.body = body
239
+ end
240
+
241
+ if self.authorization.respond_to?(:generate_authenticated_request)
242
+ http_request = self.authorization.generate_authenticated_request(
243
+ :request => http_request,
244
+ :connection => connection
245
+ )
246
+ end
247
+
248
+ request_env = http_request.to_env(connection)
249
+ end
250
+
251
+ ##
252
+ # Convert HTTP response to an API Result
253
+ #
254
+ # @api private
255
+ #
256
+ # @param [Faraday::Response] response
257
+ # HTTP response
258
+ #
259
+ # @return [Google::APIClient::Result]
260
+ # Processed API response
261
+ def process_http_response(response)
262
+ Result.new(self, response)
263
+ end
264
+
265
+ protected
266
+
267
+ ##
268
+ # Adjust headers & body for media uploads
269
+ #
270
+ # @api private
271
+ #
272
+ # @param [Hash] options
273
+ # @option options [Hash, Array] :parameters
274
+ # Request parameters for the API method.
275
+ # @option options [Google::APIClient::UploadIO] :media
276
+ # File to upload, if media upload request
277
+ # @option options [#to_json, #to_hash] :body_object
278
+ # Main body of the API request. Typically hash or object that can
279
+ # be serialized to JSON
280
+ # @option options [#read, #to_str] :body
281
+ # Raw body to send in POST/PUT requests
282
+ def initialize_media_upload(options)
283
+ self.media = options[:media]
284
+ case self.upload_type
285
+ when "media"
286
+ if options[:body] || options[:body_object]
287
+ raise ArgumentError, "Can not specify body & body object for simple uploads"
288
+ end
289
+ self.headers['Content-Type'] ||= self.media.content_type
290
+ self.headers['Content-Length'] ||= self.media.length.to_s
291
+ self.body = self.media
292
+ when "multipart"
293
+ unless options[:body_object]
294
+ raise ArgumentError, "Multipart requested but no body object"
295
+ end
296
+ metadata = StringIO.new(serialize_body(options[:body_object]))
297
+ build_multipart([Faraday::UploadIO.new(metadata, 'application/json', 'file.json'), self.media])
298
+ when "resumable"
299
+ file_length = self.media.length
300
+ self.headers['X-Upload-Content-Type'] = self.media.content_type
301
+ self.headers['X-Upload-Content-Length'] = file_length.to_s
302
+ if options[:body_object]
303
+ self.headers['Content-Type'] ||= 'application/json'
304
+ self.body = serialize_body(options[:body_object])
305
+ else
306
+ self.body = ''
307
+ end
308
+ end
309
+ end
310
+
311
+ ##
312
+ # Assemble a multipart message from a set of parts
313
+ #
314
+ # @api private
315
+ #
316
+ # @param [Array<[#read,#to_str]>] parts
317
+ # Array of parts to encode.
318
+ # @param [String] mime_type
319
+ # MIME type of the message
320
+ # @param [String] boundary
321
+ # Boundary for separating each part of the message
322
+ def build_multipart(parts, mime_type = 'multipart/related', boundary = MULTIPART_BOUNDARY)
323
+ env = Faraday::Env.new
324
+ env.request = Faraday::RequestOptions.new
325
+ env.request.boundary = boundary
326
+ env.request_headers = {'Content-Type' => "#{mime_type};boundary=#{boundary}"}
327
+ multipart = Faraday::Request::Multipart.new
328
+ self.body = multipart.create_multipart(env, parts.map {|part| [nil, part]})
329
+ self.headers.update(env[:request_headers])
330
+ end
331
+
332
+ ##
333
+ # Serialize body object to JSON
334
+ #
335
+ # @api private
336
+ #
337
+ # @param [#to_json,#to_hash] body
338
+ # object to serialize
339
+ #
340
+ # @return [String]
341
+ # JSON
342
+ def serialize_body(body)
343
+ return body.to_json if body.respond_to?(:to_json)
344
+ return MultiJson.dump(body.to_hash) if body.respond_to?(:to_hash)
345
+ raise TypeError, 'Could not convert body object to JSON.' +
346
+ 'Must respond to :to_json or :to_hash.'
347
+ end
348
+
349
+ end
350
+ end
351
+ end
@@ -0,0 +1,253 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ module Google
17
+ class APIClient
18
+ ##
19
+ # This class wraps a result returned by an API call.
20
+ class Result
21
+ extend Forwardable
22
+
23
+ ##
24
+ # Init the result
25
+ #
26
+ # @param [Google::APIClient::Request] request
27
+ # The original request
28
+ # @param [Faraday::Response] response
29
+ # Raw HTTP Response
30
+ def initialize(request, response)
31
+ @request = request
32
+ @response = response
33
+ @media_upload = reference if reference.kind_of?(ResumableUpload)
34
+ end
35
+
36
+ # @return [Google::APIClient::Request] Original request object
37
+ attr_reader :request
38
+ # @return [Faraday::Response] HTTP response
39
+ attr_reader :response
40
+ # @!attribute [r] reference
41
+ # @return [Google::APIClient::Request] Original request object
42
+ # @deprecated See {#request}
43
+ alias_method :reference, :request # For compatibility with pre-beta clients
44
+
45
+ # @!attribute [r] status
46
+ # @return [Fixnum] HTTP status code
47
+ # @!attribute [r] headers
48
+ # @return [Hash] HTTP response headers
49
+ # @!attribute [r] body
50
+ # @return [String] HTTP response body
51
+ def_delegators :@response, :status, :headers, :body
52
+
53
+ # @!attribute [r] resumable_upload
54
+ # @return [Google::APIClient::ResumableUpload] For resuming media uploads
55
+ def resumable_upload
56
+ @media_upload ||= (
57
+ options = self.reference.to_hash.merge(
58
+ :uri => self.headers['location'],
59
+ :media => self.reference.media
60
+ )
61
+ Google::APIClient::ResumableUpload.new(options)
62
+ )
63
+ end
64
+
65
+ ##
66
+ # Get the content type of the response
67
+ # @!attribute [r] media_type
68
+ # @return [String]
69
+ # Value of content-type header
70
+ def media_type
71
+ _, content_type = self.headers.detect do |h, v|
72
+ h.downcase == 'Content-Type'.downcase
73
+ end
74
+ if content_type
75
+ return content_type[/^([^;]*);?.*$/, 1].strip.downcase
76
+ else
77
+ return nil
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Check if request failed
83
+ #
84
+ # @!attribute [r] error?
85
+ # @return [TrueClass, FalseClass]
86
+ # true if result of operation is an error
87
+ def error?
88
+ return self.response.status >= 400
89
+ end
90
+
91
+ ##
92
+ # Check if request was successful
93
+ #
94
+ # @!attribute [r] success?
95
+ # @return [TrueClass, FalseClass]
96
+ # true if result of operation was successful
97
+ def success?
98
+ return !self.error?
99
+ end
100
+
101
+ ##
102
+ # Extracts error messages from the response body
103
+ #
104
+ # @!attribute [r] error_message
105
+ # @return [String]
106
+ # error message, if available
107
+ def error_message
108
+ if self.data?
109
+ if self.data.respond_to?(:error) &&
110
+ self.data.error.respond_to?(:message)
111
+ # You're going to get a terrible error message if the response isn't
112
+ # parsed successfully as an error.
113
+ return self.data.error.message
114
+ elsif self.data['error'] && self.data['error']['message']
115
+ return self.data['error']['message']
116
+ end
117
+ end
118
+ return self.body
119
+ end
120
+
121
+ ##
122
+ # Check for parsable data in response
123
+ #
124
+ # @!attribute [r] data?
125
+ # @return [TrueClass, FalseClass]
126
+ # true if body can be parsed
127
+ def data?
128
+ !(self.body.nil? || self.body.empty? || self.media_type != 'application/json')
129
+ end
130
+
131
+ ##
132
+ # Return parsed version of the response body.
133
+ #
134
+ # @!attribute [r] data
135
+ # @return [Object, Hash, String]
136
+ # Object if body parsable from API schema, Hash if JSON, raw body if unable to parse
137
+ def data
138
+ return @data ||= (begin
139
+ if self.data?
140
+ media_type = self.media_type
141
+ data = self.body
142
+ case media_type
143
+ when 'application/json'
144
+ data = MultiJson.load(data)
145
+ # Strip data wrapper, if present
146
+ data = data['data'] if data.has_key?('data')
147
+ else
148
+ raise ArgumentError,
149
+ "Content-Type not supported for parsing: #{media_type}"
150
+ end
151
+ if @request.api_method && @request.api_method.response_schema
152
+ # Automatically parse using the schema designated for the
153
+ # response of this API method.
154
+ data = @request.api_method.response_schema.new(data)
155
+ data
156
+ else
157
+ # Otherwise, return the raw unparsed value.
158
+ # This value must be indexable like a Hash.
159
+ data
160
+ end
161
+ end
162
+ end)
163
+ end
164
+
165
+ ##
166
+ # Get the token used for requesting the next page of data
167
+ #
168
+ # @!attribute [r] next_page_token
169
+ # @return [String]
170
+ # next page token
171
+ def next_page_token
172
+ if self.data.respond_to?(:next_page_token)
173
+ return self.data.next_page_token
174
+ elsif self.data.respond_to?(:[])
175
+ return self.data["nextPageToken"]
176
+ else
177
+ raise TypeError, "Data object did not respond to #next_page_token."
178
+ end
179
+ end
180
+
181
+ ##
182
+ # Build a request for fetching the next page of data
183
+ #
184
+ # @return [Google::APIClient::Request]
185
+ # API request for retrieving next page
186
+ def next_page
187
+ merged_parameters = Hash[self.reference.parameters].merge({
188
+ self.page_token_param => self.next_page_token
189
+ })
190
+ # Because Requests can be coerced to Hashes, we can merge them,
191
+ # preserving all context except the API method parameters that we're
192
+ # using for pagination.
193
+ return Google::APIClient::Request.new(
194
+ Hash[self.reference].merge(:parameters => merged_parameters)
195
+ )
196
+ end
197
+
198
+ ##
199
+ # Get the token used for requesting the previous page of data
200
+ #
201
+ # @!attribute [r] prev_page_token
202
+ # @return [String]
203
+ # previous page token
204
+ def prev_page_token
205
+ if self.data.respond_to?(:prev_page_token)
206
+ return self.data.prev_page_token
207
+ elsif self.data.respond_to?(:[])
208
+ return self.data["prevPageToken"]
209
+ else
210
+ raise TypeError, "Data object did not respond to #next_page_token."
211
+ end
212
+ end
213
+
214
+ ##
215
+ # Build a request for fetching the previous page of data
216
+ #
217
+ # @return [Google::APIClient::Request]
218
+ # API request for retrieving previous page
219
+ def prev_page
220
+ merged_parameters = Hash[self.reference.parameters].merge({
221
+ self.page_token_param => self.prev_page_token
222
+ })
223
+ # Because Requests can be coerced to Hashes, we can merge them,
224
+ # preserving all context except the API method parameters that we're
225
+ # using for pagination.
226
+ return Google::APIClient::Request.new(
227
+ Hash[self.reference].merge(:parameters => merged_parameters)
228
+ )
229
+ end
230
+
231
+ ##
232
+ # Pagination scheme used by this request/response
233
+ #
234
+ # @!attribute [r] pagination_type
235
+ # @return [Symbol]
236
+ # currently always :token
237
+ def pagination_type
238
+ return :token
239
+ end
240
+
241
+ ##
242
+ # Name of the field that contains the pagination token
243
+ #
244
+ # @!attribute [r] page_token_param
245
+ # @return [String]
246
+ # currently always 'pageToken'
247
+ def page_token_param
248
+ return "pageToken"
249
+ end
250
+
251
+ end
252
+ end
253
+ end