google-cloud-bigquery 1.14.0 → 1.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +17 -54
  3. data/CHANGELOG.md +377 -0
  4. data/CONTRIBUTING.md +328 -116
  5. data/LOGGING.md +1 -1
  6. data/OVERVIEW.md +21 -20
  7. data/TROUBLESHOOTING.md +2 -8
  8. data/lib/google/cloud/bigquery/argument.rb +197 -0
  9. data/lib/google/cloud/bigquery/convert.rb +155 -173
  10. data/lib/google/cloud/bigquery/copy_job.rb +74 -26
  11. data/lib/google/cloud/bigquery/credentials.rb +5 -12
  12. data/lib/google/cloud/bigquery/data.rb +109 -18
  13. data/lib/google/cloud/bigquery/dataset/access.rb +474 -52
  14. data/lib/google/cloud/bigquery/dataset/list.rb +7 -13
  15. data/lib/google/cloud/bigquery/dataset/tag.rb +67 -0
  16. data/lib/google/cloud/bigquery/dataset.rb +1044 -287
  17. data/lib/google/cloud/bigquery/external/avro_source.rb +107 -0
  18. data/lib/google/cloud/bigquery/external/bigtable_source/column.rb +404 -0
  19. data/lib/google/cloud/bigquery/external/bigtable_source/column_family.rb +945 -0
  20. data/lib/google/cloud/bigquery/external/bigtable_source.rb +230 -0
  21. data/lib/google/cloud/bigquery/external/csv_source.rb +481 -0
  22. data/lib/google/cloud/bigquery/external/data_source.rb +771 -0
  23. data/lib/google/cloud/bigquery/external/json_source.rb +170 -0
  24. data/lib/google/cloud/bigquery/external/parquet_source.rb +148 -0
  25. data/lib/google/cloud/bigquery/external/sheets_source.rb +166 -0
  26. data/lib/google/cloud/bigquery/external.rb +50 -2256
  27. data/lib/google/cloud/bigquery/extract_job.rb +226 -61
  28. data/lib/google/cloud/bigquery/insert_response.rb +1 -3
  29. data/lib/google/cloud/bigquery/job/list.rb +10 -14
  30. data/lib/google/cloud/bigquery/job.rb +289 -14
  31. data/lib/google/cloud/bigquery/load_job.rb +810 -136
  32. data/lib/google/cloud/bigquery/model/list.rb +5 -9
  33. data/lib/google/cloud/bigquery/model.rb +247 -16
  34. data/lib/google/cloud/bigquery/policy.rb +432 -0
  35. data/lib/google/cloud/bigquery/project/list.rb +6 -11
  36. data/lib/google/cloud/bigquery/project.rb +509 -250
  37. data/lib/google/cloud/bigquery/query_job.rb +594 -128
  38. data/lib/google/cloud/bigquery/routine/list.rb +165 -0
  39. data/lib/google/cloud/bigquery/routine.rb +1227 -0
  40. data/lib/google/cloud/bigquery/schema/field.rb +413 -63
  41. data/lib/google/cloud/bigquery/schema.rb +221 -48
  42. data/lib/google/cloud/bigquery/service.rb +204 -112
  43. data/lib/google/cloud/bigquery/standard_sql.rb +269 -53
  44. data/lib/google/cloud/bigquery/table/async_inserter.rb +86 -43
  45. data/lib/google/cloud/bigquery/table/list.rb +6 -11
  46. data/lib/google/cloud/bigquery/table.rb +1470 -377
  47. data/lib/google/cloud/bigquery/time.rb +6 -0
  48. data/lib/google/cloud/bigquery/version.rb +1 -1
  49. data/lib/google/cloud/bigquery.rb +4 -6
  50. data/lib/google-cloud-bigquery.rb +14 -13
  51. metadata +66 -38
@@ -0,0 +1,432 @@
1
+ # Copyright 2020 Google LLC
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
+ # https://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
+ require "google/apis/bigquery_v2"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Bigquery
21
+ ##
22
+ # # Policy
23
+ #
24
+ # Represents a Cloud IAM Policy for BigQuery resources.
25
+ #
26
+ # A Policy is a collection of bindings. A {Policy::Binding} binds one or more members to a single role. Member
27
+ # strings can describe user accounts, service accounts, Google groups, and domains. A role string represents a
28
+ # named list of permissions; each role can be an IAM predefined role or a user-created custom role.
29
+ #
30
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
31
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
32
+ #
33
+ # @attr [String] etag Used to check if the policy has changed since the last request. When you make a request with
34
+ # an `etag` value, Cloud IAM compares the `etag` value in the request with the existing `etag` value associated
35
+ # with the policy. It writes the policy only if the `etag` values match.
36
+ # @attr [Array<Binding>] bindings The bindings in the policy, which may be mutable or frozen depending on the
37
+ # context. See [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of
38
+ # primitive and curated roles. See [BigQuery Table ACL
39
+ # permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
40
+ # values and patterns for members.
41
+ #
42
+ # @example
43
+ # require "google/cloud/bigquery"
44
+ #
45
+ # bigquery = Google::Cloud::Bigquery.new
46
+ # dataset = bigquery.dataset "my_dataset"
47
+ # table = dataset.table "my_table"
48
+ # policy = table.policy
49
+ #
50
+ # policy.frozen? #=> true
51
+ # binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
52
+ #
53
+ # binding_owner.role #=> "roles/owner"
54
+ # binding_owner.members #=> ["user:owner@example.com"]
55
+ # binding_owner.frozen? #=> true
56
+ # binding_owner.members.frozen? #=> true
57
+ #
58
+ # @example Update mutable bindings in the policy.
59
+ # require "google/cloud/bigquery"
60
+ #
61
+ # bigquery = Google::Cloud::Bigquery.new
62
+ # dataset = bigquery.dataset "my_dataset"
63
+ # table = dataset.table "my_table"
64
+ #
65
+ # table.update_policy do |p|
66
+ # p.grant role: "roles/viewer", members: "user:viewer@example.com"
67
+ # p.revoke role: "roles/editor", members: "user:editor@example.com"
68
+ # p.revoke role: "roles/owner"
69
+ # end
70
+ #
71
+ # @example Iterate over frozen bindings.
72
+ # require "google/cloud/bigquery"
73
+ #
74
+ # bigquery = Google::Cloud::Bigquery.new
75
+ # dataset = bigquery.dataset "my_dataset"
76
+ # table = dataset.table "my_table"
77
+ # policy = table.policy
78
+ #
79
+ # policy.frozen? #=> true
80
+ # policy.bindings.each do |b|
81
+ # puts b.role
82
+ # puts b.members
83
+ # end
84
+ #
85
+ # @example Update mutable bindings.
86
+ # require "google/cloud/bigquery"
87
+ #
88
+ # bigquery = Google::Cloud::Bigquery.new
89
+ # dataset = bigquery.dataset "my_dataset"
90
+ # table = dataset.table "my_table"
91
+ #
92
+ # table.update_policy do |p|
93
+ # p.bindings.each do |b|
94
+ # b.members.delete_if { |m| m.include? "@example.com" }
95
+ # end
96
+ # end
97
+ #
98
+ class Policy
99
+ attr_reader :etag
100
+ attr_reader :bindings
101
+
102
+ # @private
103
+ def initialize etag, bindings
104
+ @etag = etag.freeze
105
+ @bindings = bindings
106
+ end
107
+
108
+ ##
109
+ # Convenience method adding or updating a binding in the policy. See [Understanding
110
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of primitive and curated roles. See
111
+ # [BigQuery Table ACL
112
+ # permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
113
+ # values and patterns for members.
114
+ #
115
+ # @param [String] role The role that is bound to members in the binding. For example, `roles/viewer`,
116
+ # `roles/editor`, or `roles/owner`. Required.
117
+ # @param [String, Array<String>] members Specifies the identities requesting access for a Cloud Platform
118
+ # resource. `members` can have the following values. Required.
119
+ #
120
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
121
+ # account.
122
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
123
+ # account or a service account.
124
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
125
+ # `alice@example.com`.
126
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
127
+ # `my-other-app@appspot.gserviceaccount.com`.
128
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
129
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
130
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
131
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
132
+ # binding.
133
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
134
+ # a service account that has been recently deleted. For example,
135
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
136
+ # this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
137
+ # the binding.
138
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
139
+ # group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
140
+ # group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
141
+ # the binding.
142
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
143
+ # `google.com` or `example.com`.
144
+ #
145
+ # @return [nil]
146
+ #
147
+ # @example Grant a role to a member.
148
+ # require "google/cloud/bigquery"
149
+ #
150
+ # bigquery = Google::Cloud::Bigquery.new
151
+ # dataset = bigquery.dataset "my_dataset"
152
+ # table = dataset.table "my_table"
153
+ #
154
+ # table.update_policy do |p|
155
+ # p.grant role: "roles/viewer", members: "user:viewer@example.com"
156
+ # end
157
+ #
158
+ def grant role:, members:
159
+ existing_binding = bindings.find { |b| b.role == role }
160
+ if existing_binding
161
+ existing_binding.members.concat Array(members)
162
+ existing_binding.members.uniq!
163
+ else
164
+ bindings << Binding.new(role, members)
165
+ end
166
+ nil
167
+ end
168
+
169
+ ##
170
+ # Convenience method for removing a binding or bindings from the policy. See
171
+ # [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of primitive and
172
+ # curated roles. See [BigQuery Table ACL
173
+ # permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
174
+ # values and patterns for members.
175
+ #
176
+ # @param [String] role A role that is bound to members in the policy. For example, `roles/viewer`,
177
+ # `roles/editor`, or `roles/owner`. Optional.
178
+ # @param [String, Array<String>] members Specifies the identities receiving access for a Cloud Platform
179
+ # resource. `members` can have the following values. Optional.
180
+ #
181
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
182
+ # account.
183
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
184
+ # account or a service account.
185
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
186
+ # `alice@example.com`.
187
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
188
+ # `my-other-app@appspot.gserviceaccount.com`.
189
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
190
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
191
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
192
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
193
+ # binding.
194
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
195
+ # a service account that has been recently deleted. For example,
196
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
197
+ # this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
198
+ # the binding.
199
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
200
+ # group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
201
+ # group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
202
+ # the binding.
203
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
204
+ # `google.com` or `example.com`.
205
+ #
206
+ # @return [nil]
207
+ #
208
+ # @example Revoke a role for a member or members.
209
+ # require "google/cloud/bigquery"
210
+ #
211
+ # bigquery = Google::Cloud::Bigquery.new
212
+ # dataset = bigquery.dataset "my_dataset"
213
+ # table = dataset.table "my_table"
214
+ #
215
+ # table.update_policy do |p|
216
+ # p.revoke role: "roles/viewer", members: "user:viewer@example.com"
217
+ # end
218
+ #
219
+ # @example Revoke a role for all members.
220
+ # require "google/cloud/bigquery"
221
+ #
222
+ # bigquery = Google::Cloud::Bigquery.new
223
+ # dataset = bigquery.dataset "my_dataset"
224
+ # table = dataset.table "my_table"
225
+ #
226
+ # table.update_policy do |p|
227
+ # p.revoke role: "roles/viewer"
228
+ # end
229
+ #
230
+ # @example Revoke all roles for a member or members.
231
+ # require "google/cloud/bigquery"
232
+ #
233
+ # bigquery = Google::Cloud::Bigquery.new
234
+ # dataset = bigquery.dataset "my_dataset"
235
+ # table = dataset.table "my_table"
236
+ #
237
+ # table.update_policy do |p|
238
+ # p.revoke members: ["user:viewer@example.com", "user:editor@example.com"]
239
+ # end
240
+ #
241
+ def revoke role: nil, members: nil
242
+ bindings_for_role = role ? bindings.select { |b| b.role == role } : bindings
243
+ bindings_for_role.each do |b|
244
+ if members
245
+ b.members -= Array(members)
246
+ bindings.delete b if b.members.empty?
247
+ else
248
+ bindings.delete b
249
+ end
250
+ end
251
+ nil
252
+ end
253
+
254
+ ##
255
+ # @private Convert the Policy to a Google::Apis::BigqueryV2::Policy.
256
+ def to_gapi
257
+ Google::Apis::BigqueryV2::Policy.new(
258
+ bindings: bindings_to_gapi,
259
+ etag: etag,
260
+ version: 1
261
+ )
262
+ end
263
+
264
+ ##
265
+ # @private Deep freeze the policy including its bindings.
266
+ def freeze
267
+ super
268
+ @bindings.each(&:freeze)
269
+ @bindings.freeze
270
+ self
271
+ end
272
+
273
+ ##
274
+ # @private New Policy from a Google::Apis::BigqueryV2::Policy object.
275
+ def self.from_gapi gapi
276
+ bindings = Array(gapi.bindings).map do |binding|
277
+ Binding.new binding.role, binding.members.to_a
278
+ end
279
+ new gapi.etag, bindings
280
+ end
281
+
282
+ ##
283
+ # # Policy::Binding
284
+ #
285
+ # Represents a Cloud IAM Binding for BigQuery resources within the context of a {Policy}.
286
+ #
287
+ # A binding binds one or more members to a single role. Member strings can describe user accounts, service
288
+ # accounts, Google groups, and domains. A role is a named list of permissions; each role can be an IAM
289
+ # predefined role or a user-created custom role.
290
+ #
291
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
292
+ #
293
+ # @attr [String] role The role that is assigned to `members`. For example, `roles/viewer`, `roles/editor`, or
294
+ # `roles/owner`. Required.
295
+ # @attr [Array<String>] members Specifies the identities requesting access for a Cloud Platform resource.
296
+ # `members` can have the following values. Required.
297
+ #
298
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
299
+ # account.
300
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
301
+ # account or a service account.
302
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
303
+ # `alice@example.com`.
304
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
305
+ # `my-other-app@appspot.gserviceaccount.com`.
306
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
307
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
308
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
309
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
310
+ # binding.
311
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
312
+ # a service account that has been recently deleted. For example,
313
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
314
+ # this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
315
+ # the binding.
316
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
317
+ # group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
318
+ # group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
319
+ # the binding.
320
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
321
+ # `google.com` or `example.com`.
322
+ #
323
+ # @example
324
+ # require "google/cloud/bigquery"
325
+ #
326
+ # bigquery = Google::Cloud::Bigquery.new
327
+ # dataset = bigquery.dataset "my_dataset"
328
+ # table = dataset.table "my_table"
329
+ #
330
+ # policy = table.policy
331
+ # binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
332
+ #
333
+ # binding_owner.role #=> "roles/owner"
334
+ # binding_owner.members #=> ["user:owner@example.com"]
335
+ #
336
+ # binding_owner.frozen? #=> true
337
+ # binding_owner.members.frozen? #=> true
338
+ #
339
+ # @example Update mutable bindings.
340
+ # require "google/cloud/bigquery"
341
+ #
342
+ # bigquery = Google::Cloud::Bigquery.new
343
+ # dataset = bigquery.dataset "my_dataset"
344
+ # table = dataset.table "my_table"
345
+ #
346
+ # table.update_policy do |p|
347
+ # binding_owner = p.bindings.find { |b| b.role == "roles/owner" }
348
+ # binding_owner.members.delete_if { |m| m.include? "@example.com" }
349
+ # end
350
+ #
351
+ class Binding
352
+ attr_accessor :role
353
+ attr_reader :members
354
+
355
+ # @private
356
+ def initialize role, members
357
+ members = Array(members).uniq
358
+ raise ArgumentError, "members cannot be empty" if members.empty?
359
+ @role = role
360
+ @members = members
361
+ end
362
+
363
+ ##
364
+ # Sets the binding members.
365
+ #
366
+ # @param [Array<String>] new_members Specifies the identities requesting access for a Cloud Platform resource.
367
+ # `new_members` can have the following values. Required.
368
+ #
369
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
370
+ # account.
371
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
372
+ # account or a service account.
373
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
374
+ # `alice@example.com`.
375
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
376
+ # `my-other-app@appspot.gserviceaccount.com`.
377
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
378
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
379
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
380
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
381
+ # binding.
382
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier)
383
+ # representing a service account that has been recently deleted. For example,
384
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is
385
+ # undeleted, this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains
386
+ # the role in the binding.
387
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a
388
+ # Google group that has been recently deleted. For example,
389
+ # `admins@example.com?uid=123456789012345678901`. If the group is recovered, this value reverts to
390
+ # `group:<emailid>` and the recovered group retains the role in the binding.
391
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For
392
+ # example, `google.com` or `example.com`.
393
+ #
394
+ def members= new_members
395
+ @members = Array(new_members).uniq
396
+ end
397
+
398
+ ##
399
+ # @private Convert the Binding to a Google::Apis::BigqueryV2::Binding.
400
+ def to_gapi
401
+ Google::Apis::BigqueryV2::Binding.new role: role, members: members
402
+ end
403
+
404
+ ##
405
+ # @private Deep freeze the policy including its members.
406
+ def freeze
407
+ super
408
+ role.freeze
409
+ members.each(&:freeze)
410
+ members.freeze
411
+ self
412
+ end
413
+
414
+ ##
415
+ # @private New Binding from a Google::Apis::BigqueryV2::Binding object.
416
+ def self.from_gapi gapi
417
+ new gapi.etag, gapi.members.to_a
418
+ end
419
+ end
420
+
421
+ protected
422
+
423
+ def bindings_to_gapi
424
+ @bindings.compact.uniq.map do |b|
425
+ next if b.members.empty?
426
+ b.to_gapi
427
+ end
428
+ end
429
+ end
430
+ end
431
+ end
432
+ end
@@ -72,8 +72,7 @@ module Google
72
72
  def next
73
73
  return nil unless next?
74
74
  ensure_service!
75
- options = { all: @hidden, token: token, max: @max }
76
- gapi = @service.list_projects options
75
+ gapi = @service.list_projects token: token, max: @max
77
76
  self.class.from_gapi gapi, @service, @max
78
77
  end
79
78
 
@@ -122,17 +121,15 @@ module Google
122
121
  # puts project.name
123
122
  # end
124
123
  #
125
- def all request_limit: nil
124
+ def all request_limit: nil, &block
126
125
  request_limit = request_limit.to_i if request_limit
127
- unless block_given?
128
- return enum_for :all, request_limit: request_limit
129
- end
126
+ return enum_for :all, request_limit: request_limit unless block_given?
130
127
  results = self
131
128
  loop do
132
- results.each { |r| yield r }
129
+ results.each(&block)
133
130
  if request_limit
134
131
  request_limit -= 1
135
- break if request_limit < 0
132
+ break if request_limit.negative?
136
133
  end
137
134
  break unless results.next?
138
135
  results = results.next
@@ -142,9 +139,7 @@ module Google
142
139
  ##
143
140
  # @private New Project::List from a response object.
144
141
  def self.from_gapi gapi_list, service, max = nil
145
- projects = List.new(Array(gapi_list.projects).map do |gapi_object|
146
- Project.from_gapi gapi_object, service
147
- end)
142
+ projects = List.new(Array(gapi_list.projects).map { |gapi_object| Project.from_gapi gapi_object, service })
148
143
  projects.instance_variable_set :@token, gapi_list.next_page_token
149
144
  projects.instance_variable_set :@etag, gapi_list.etag
150
145
  projects.instance_variable_set :@service, service