google-cloud-firestore 2.2.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c1c6b4bcea222f6ed81150700b9d6c969fc70eeb8492db0ed69db1bb43f62cb
4
- data.tar.gz: 50bbd220cf388af656606d99948477d47f9a1fa3d41ab479f6fcaa32f32e909d
3
+ metadata.gz: 8d0f9ea11dcd132795aca2ffe91250ca03fce477e6fdcb3aafc7e9d01560b172
4
+ data.tar.gz: 3701797b2412e82cdf227fe9d162291e53e2aaf4a1c3cc8d37d18ea0a9795f1c
5
5
  SHA512:
6
- metadata.gz: d1a810ae1cd779858ad8762dacd08765b2daf06b1de8ce13dc675b79ef7c6696c3bbda34d7593a6087e2189aebd2e23090bd89d11da8753f1751726270a61391
7
- data.tar.gz: af77949c47636ca6e65ca14224fa5270a9f3daa4c00fd236e19780273e35593c0986ba5e5a0d601a6f107cbdc5482db51ca002841ee8cbf21acbd9ac752a93ee
6
+ metadata.gz: e8ce0745147c89e081b94f08a3753bc0a234f1a2e9a5eb9eb15cfc798abbb01e5970fb354db0ff6b71096353dabe2a023e8cba7d5d4c909f20793f953473044d
7
+ data.tar.gz: 489e87876e77584f429472f12c157b0c1412d336190b3a8a88e706e262c3d0409b4b00c55207ebd6cab15f0a6ae7b1ad45177c8dfcc87408cd96384db1a11038
data/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Release History
2
2
 
3
+ ### 2.5.1 / 2021-04-19
4
+
5
+ #### Bug Fixes
6
+
7
+ * Add GRPC::Unknown to retryable errors in Watch::Listener
8
+
9
+ ### 2.5.0 / 2021-03-10
10
+
11
+ #### Features
12
+
13
+ * Drop support for Ruby 2.4 and add support for Ruby 3.0
14
+
15
+ ### 2.4.1 / 2021-01-06
16
+
17
+ #### Bug Fixes
18
+
19
+ * Replace usage of Write.transform with Write.update_transforms
20
+
21
+ ### 2.4.0 / 2020-11-19
22
+
23
+ #### Features
24
+
25
+ * add support for != and NOT_IN queries
26
+
27
+ ### 2.3.0 / 2020-09-30
28
+
29
+ #### Features
30
+
31
+ * Add error callbacks for listener threads
32
+ * Add DocumentListener#last_error
33
+ * Add DocumentListener#on_error
34
+ * Add QueryListener#last_error
35
+ * Add QueryListener#on_error
36
+
3
37
  ### 2.2.0 / 2020-09-17
4
38
 
5
39
  #### Features
data/CONTRIBUTING.md CHANGED
@@ -24,7 +24,7 @@ be able to accept your pull requests.
24
24
  In order to use the google-cloud-firestore console and run the project's tests,
25
25
  there is a small amount of setup:
26
26
 
27
- 1. Install Ruby. google-cloud-firestore requires Ruby 2.4+. You may choose to
27
+ 1. Install Ruby. google-cloud-firestore requires Ruby 2.5+. You may choose to
28
28
  manage your Ruby and gem installations with [RVM](https://rvm.io/),
29
29
  [rbenv](https://github.com/rbenv/rbenv), or
30
30
  [chruby](https://github.com/postmodern/chruby).
@@ -45,7 +45,7 @@ there is a small amount of setup:
45
45
 
46
46
  ```sh
47
47
  $ cd google-cloud-firestore/
48
- $ bundle exec rake bundleupdate
48
+ $ bundle install
49
49
  ```
50
50
 
51
51
  ## Console
@@ -119,15 +119,14 @@ If you alter an example's title, you may encounter breaking tests.
119
119
  ### Firestore Acceptance Tests
120
120
 
121
121
  The Firestore acceptance tests interact with the live service API. Follow the
122
- instructions in the {file:AUTHENTICATION.md Authentication guide} for enabling
122
+ instructions in the {file:AUTHENTICATION.md Authentication Guide} for enabling
123
123
  the Firestore API. Occasionally, some API features may not yet be generally
124
124
  available, making it difficult for some contributors to successfully run the
125
125
  entire acceptance test suite. However, please ensure that you do successfully
126
126
  run acceptance tests for any code areas covered by your pull request.
127
127
 
128
128
  To run the acceptance tests, first create and configure a project in the Google
129
- Developers Console, as described in the {file:AUTHENTICATION.md Authentication
130
- guide}. Be sure to download the JSON KEY file. Make note of the PROJECT_ID and
129
+ Developers Console, as described in the {file:AUTHENTICATION.md Authentication Guide}. Be sure to download the JSON KEY file. Make note of the PROJECT_ID and
131
130
  the KEYFILE location on your system.
132
131
 
133
132
  Before you can run the Firestore acceptance tests, you must first create indexes
data/LOGGING.md CHANGED
@@ -3,7 +3,7 @@
3
3
  To enable logging for this library, set the logger for the underlying
4
4
  [gRPC](https://github.com/grpc/grpc/tree/master/src/ruby) library. The logger
5
5
  that you set may be a Ruby stdlib
6
- [`Logger`](https://ruby-doc.org/stdlib-2.5.0/libdoc/logger/rdoc/Logger.html) as
6
+ [`Logger`](https://ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html) as
7
7
  shown below, or a
8
8
  [`Google::Cloud::Logging::Logger`](https://googleapis.dev/ruby/google-cloud-logging/latest)
9
9
  that will write logs to [Stackdriver
@@ -119,7 +119,7 @@ module Google
119
119
 
120
120
  doc_path = coalesce_doc_path_argument doc
121
121
 
122
- @writes << Convert.writes_for_create(doc_path, data)
122
+ @writes << Convert.write_for_create(doc_path, data)
123
123
 
124
124
  nil
125
125
  end
@@ -218,7 +218,7 @@ module Google
218
218
 
219
219
  doc_path = coalesce_doc_path_argument doc
220
220
 
221
- @writes << Convert.writes_for_set(doc_path, data, merge: merge)
221
+ @writes << Convert.write_for_set(doc_path, data, merge: merge)
222
222
 
223
223
  nil
224
224
  end
@@ -322,8 +322,7 @@ module Google
322
322
 
323
323
  doc_path = coalesce_doc_path_argument doc
324
324
 
325
- @writes << Convert.writes_for_update(doc_path, data,
326
- update_time: update_time)
325
+ @writes << Convert.write_for_update(doc_path, data, update_time: update_time)
327
326
 
328
327
  nil
329
328
  end
@@ -100,11 +100,11 @@ module Google
100
100
  # puts col.collection_id
101
101
  # end
102
102
  #
103
- def cols
103
+ def cols &block
104
104
  ensure_service!
105
105
  grpc = service.list_collections "#{path}/documents"
106
106
  cols_enum = CollectionReferenceList.from_grpc(grpc, self, "#{path}/documents").all
107
- cols_enum.each { |c| yield c } if block_given?
107
+ cols_enum.each(&block) if block_given?
108
108
  cols_enum
109
109
  end
110
110
  alias collections cols
@@ -256,7 +256,7 @@ module Google
256
256
  ensure_service!
257
257
 
258
258
  unless block_given?
259
- return enum_for :get_all, docs, field_mask: field_mask
259
+ return enum_for :get_all, *docs, field_mask: field_mask
260
260
  end
261
261
 
262
262
  doc_paths = Array(docs).flatten.map do |doc_path|
@@ -634,9 +634,9 @@ module Google
634
634
  commit_return = transaction.commit
635
635
  # Conditional return value, depending on truthy commit_response
636
636
  commit_response ? commit_return : transaction_return
637
- rescue Google::Cloud::UnavailableError => err
637
+ rescue Google::Cloud::UnavailableError => e
638
638
  # Re-raise if retried more than the max
639
- raise err if backoff[:current] > backoff[:max]
639
+ raise e if backoff[:current] > backoff[:max]
640
640
 
641
641
  # Sleep with incremental backoff before restarting
642
642
  sleep backoff[:delay]
@@ -649,18 +649,18 @@ module Google
649
649
  transaction = Transaction.from_client \
650
650
  self, previous_transaction: transaction.transaction_id
651
651
  retry
652
- rescue Google::Cloud::InvalidArgumentError => err
652
+ rescue Google::Cloud::InvalidArgumentError => e
653
653
  # Return if a previous call was retried but ultimately succeeded
654
- return nil if backoff[:current] > 0
654
+ return nil if backoff[:current].positive?
655
655
 
656
656
  # Re-raise error.
657
- raise err
658
- rescue StandardError => err
657
+ raise e
658
+ rescue StandardError => e
659
659
  # Rollback transaction when handling unexpected error
660
660
  transaction.rollback rescue nil
661
661
 
662
662
  # Re-raise error.
663
- raise err
663
+ raise e
664
664
  end
665
665
  end
666
666
 
@@ -90,17 +90,17 @@ module Google
90
90
  # collection_reference.collection_id
91
91
  # end
92
92
  #
93
- def all request_limit: nil
93
+ def all request_limit: nil, &block
94
94
  request_limit = request_limit.to_i if request_limit
95
95
  unless block_given?
96
96
  return enum_for :all, request_limit: request_limit
97
97
  end
98
98
  results = self
99
99
  loop do
100
- results.each { |r| yield r }
100
+ results.each(&block)
101
101
  if request_limit
102
102
  request_limit -= 1
103
- break if request_limit < 0
103
+ break if request_limit.negative?
104
104
  end
105
105
  break unless results.next?
106
106
  results = results.next
@@ -24,7 +24,12 @@ module Google
24
24
  ##
25
25
  # @private Helper module for converting Protobuf values.
26
26
  module Convert
27
- # rubocop:disable all
27
+ # rubocop:disable Metrics/AbcSize
28
+ # rubocop:disable Metrics/BlockLength
29
+ # rubocop:disable Metrics/CyclomaticComplexity
30
+ # rubocop:disable Metrics/MethodLength
31
+ # rubocop:disable Metrics/ModuleLength
32
+ # rubocop:disable Metrics/PerceivedComplexity
28
33
  module ClassMethods
29
34
  def time_to_timestamp time
30
35
  return nil if time.nil?
@@ -32,9 +37,10 @@ module Google
32
37
  # Force the object to be a Time object.
33
38
  time = time.to_time
34
39
 
35
- Google::Protobuf::Timestamp.new \
40
+ Google::Protobuf::Timestamp.new(
36
41
  seconds: time.to_i,
37
- nanos: time.nsec
42
+ nanos: time.nsec
43
+ )
38
44
  end
39
45
 
40
46
  def timestamp_to_time timestamp
@@ -100,9 +106,10 @@ module Google
100
106
  elsif Google::Cloud::Firestore::DocumentReference === obj
101
107
  Google::Cloud::Firestore::V1::Value.new reference_value: obj.path
102
108
  elsif Array === obj
103
- values = obj.map { |o| raw_to_value(o) }
104
- Google::Cloud::Firestore::V1::Value.new(array_value:
105
- Google::Cloud::Firestore::V1::ArrayValue.new(values: values))
109
+ values = obj.map { |o| raw_to_value o }
110
+ Google::Cloud::Firestore::V1::Value.new(
111
+ array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: values)
112
+ )
106
113
  elsif Hash === obj
107
114
  # keys have been changed to strings before the hash gets here
108
115
  geo_pairs = hash_is_geo_point? obj
@@ -112,8 +119,9 @@ module Google
112
119
  )
113
120
  else
114
121
  fields = hash_to_fields obj
115
- Google::Cloud::Firestore::V1::Value.new(map_value:
116
- Google::Cloud::Firestore::V1::MapValue.new(fields: fields))
122
+ Google::Cloud::Firestore::V1::Value.new(
123
+ map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: fields)
124
+ )
117
125
  end
118
126
  elsif obj.respond_to?(:read) && obj.respond_to?(:rewind)
119
127
  obj.rewind
@@ -129,9 +137,7 @@ module Google
129
137
  return false unless hash.keys.count == 2
130
138
 
131
139
  pairs = hash.map { |k, v| [String(k), v] }.sort
132
- if pairs.map(&:first) == ["latitude", "longitude"]
133
- pairs
134
- end
140
+ pairs if pairs.map(&:first) == ["latitude", "longitude"]
135
141
  end
136
142
 
137
143
  def hash_to_geo_point hash, pairs = nil
@@ -140,47 +146,39 @@ module Google
140
146
  raise ArgumentError, "value is not a geo point" unless pairs
141
147
 
142
148
  Google::Type::LatLng.new(
143
- latitude: pairs.first.last,
144
- longitude: pairs.last.last,
149
+ latitude: pairs.first.last,
150
+ longitude: pairs.last.last
145
151
  )
146
152
  end
147
153
 
148
- def writes_for_create doc_path, data
149
- writes = []
150
-
151
- if is_field_value_nested data, :delete
154
+ def write_for_create doc_path, data
155
+ if field_value_nested? data, :delete
152
156
  raise ArgumentError, "DELETE not allowed on create"
153
157
  end
154
158
  raise ArgumentError, "data is required" unless data.is_a? Hash
155
159
 
156
160
  data, field_paths_and_values = remove_field_value_from data
157
161
 
158
- if data.any? || field_paths_and_values.empty?
159
- write = Google::Cloud::Firestore::V1::Write.new(
160
- update: Google::Cloud::Firestore::V1::Document.new(
161
- name: doc_path,
162
- fields: hash_to_fields(data)),
163
- current_document: Google::Cloud::Firestore::V1::Precondition.new(
164
- exists: false)
165
- )
166
- writes << write
167
- end
168
-
169
- if field_paths_and_values.any?
170
- transform_write = transform_write doc_path, field_paths_and_values
171
-
172
- if data.empty?
173
- transform_write.current_document = \
174
- Google::Cloud::Firestore::V1::Precondition.new(exists: false)
175
- end
176
-
177
- writes << transform_write
178
- end
162
+ doc = Google::Cloud::Firestore::V1::Document.new(
163
+ name: doc_path,
164
+ fields: hash_to_fields(data)
165
+ )
166
+ precondition = Google::Cloud::Firestore::V1::Precondition.new exists: false
167
+ Google::Cloud::Firestore::V1::Write.new(
168
+ update: doc,
169
+ current_document: precondition,
170
+ update_transforms: field_transforms(field_paths_and_values)
171
+ )
172
+ end
179
173
 
180
- writes
174
+ def field_transforms paths
175
+ return nil if paths.empty?
176
+ paths.map do |field_path, field_value|
177
+ to_field_transform field_path, field_value
178
+ end.to_a
181
179
  end
182
180
 
183
- def writes_for_set doc_path, data, merge: nil
181
+ def write_for_set doc_path, data, merge: nil
184
182
  raise ArgumentError, "data is required" unless data.is_a? Hash
185
183
 
186
184
  if merge
@@ -195,11 +193,9 @@ module Google
195
193
  end
196
194
  allow_empty = false
197
195
  end
198
- return writes_for_set_merge doc_path, data, field_paths, allow_empty
196
+ return write_for_set_merge doc_path, data, field_paths, allow_empty
199
197
  end
200
198
 
201
- writes = []
202
-
203
199
  data, delete_paths = remove_field_value_from data, :delete
204
200
  if delete_paths.any?
205
201
  raise ArgumentError, "DELETE not allowed on set"
@@ -207,30 +203,25 @@ module Google
207
203
 
208
204
  data, field_paths_and_values = remove_field_value_from data
209
205
 
210
- writes << Google::Cloud::Firestore::V1::Write.new(
211
- update: Google::Cloud::Firestore::V1::Document.new(
212
- name: doc_path,
213
- fields: hash_to_fields(data))
206
+ doc = Google::Cloud::Firestore::V1::Document.new(
207
+ name: doc_path,
208
+ fields: hash_to_fields(data)
209
+ )
210
+ Google::Cloud::Firestore::V1::Write.new(
211
+ update: doc,
212
+ update_transforms: field_transforms(field_paths_and_values)
214
213
  )
215
-
216
- if field_paths_and_values.any?
217
- writes << transform_write(doc_path, field_paths_and_values)
218
- end
219
-
220
- writes
221
214
  end
222
215
 
223
- def writes_for_set_merge doc_path, data, field_paths, allow_empty
216
+ def write_for_set_merge doc_path, data, field_paths, allow_empty
224
217
  raise ArgumentError, "data is required" unless data.is_a? Hash
225
218
 
226
219
  validate_field_paths! field_paths
227
220
 
228
- writes = []
229
-
230
221
  # Ensure provided field paths are valid.
231
222
  all_valid = identify_leaf_nodes data
232
223
  all_valid_check = field_paths.map do |verify_path|
233
- if all_valid.include?(verify_path)
224
+ if all_valid.include? verify_path
234
225
  true
235
226
  else
236
227
  found_in_all_valid = all_valid.select do |fp|
@@ -271,32 +262,25 @@ module Google
271
262
  # Restore delete paths
272
263
  field_paths += delete_field_paths_and_values.keys
273
264
 
274
- if data.empty? && !allow_empty
275
- if field_paths_and_values.empty? && delete_field_paths_and_values.empty?
276
- raise ArgumentError, "data required for set with merge"
277
- end
265
+ if data.empty? && !allow_empty && field_paths_and_values.empty? && delete_field_paths_and_values.empty?
266
+ raise ArgumentError, "data required for set with merge"
278
267
  end
279
268
 
280
- if data.any? || field_paths.any? || (allow_empty && field_paths_and_values.empty?)
281
- writes << Google::Cloud::Firestore::V1::Write.new(
282
- update: Google::Cloud::Firestore::V1::Document.new(
283
- name: doc_path,
284
- fields: hash_to_fields(data)),
285
- update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(
286
- field_paths: field_paths.map(&:formatted_string).sort)
287
- )
288
- end
289
-
290
- if field_paths_and_values.any?
291
- writes << transform_write(doc_path, field_paths_and_values)
292
- end
293
-
294
- writes
269
+ doc = Google::Cloud::Firestore::V1::Document.new(
270
+ name: doc_path,
271
+ fields: hash_to_fields(data)
272
+ )
273
+ doc_mask = Google::Cloud::Firestore::V1::DocumentMask.new(
274
+ field_paths: field_paths.map(&:formatted_string).sort
275
+ )
276
+ Google::Cloud::Firestore::V1::Write.new(
277
+ update: doc,
278
+ update_mask: doc_mask,
279
+ update_transforms: field_transforms(field_paths_and_values)
280
+ )
295
281
  end
296
282
 
297
- def writes_for_update doc_path, data, update_time: nil
298
- writes = []
299
-
283
+ def write_for_update doc_path, data, update_time: nil
300
284
  raise ArgumentError, "data is required" unless data.is_a? Hash
301
285
 
302
286
  # Convert data to use FieldPath
@@ -308,11 +292,11 @@ module Google
308
292
  # Duplicate field paths check
309
293
  validate_field_paths! new_data_pairs.map(&:first)
310
294
 
311
- delete_paths, new_data_pairs = new_data_pairs.partition do |field_path, value|
295
+ delete_paths, new_data_pairs = new_data_pairs.partition do |_field_path, value|
312
296
  value.is_a?(FieldValue) && value.type == :delete
313
297
  end
314
298
 
315
- root_field_paths_and_values, new_data_pairs = new_data_pairs.partition do |field_path, value|
299
+ root_field_paths_and_values, new_data_pairs = new_data_pairs.partition do |_field_path, value|
316
300
  value.is_a? FieldValue
317
301
  end
318
302
 
@@ -325,7 +309,7 @@ module Google
325
309
  data, nested_deletes = remove_field_value_from data, :delete
326
310
  raise ArgumentError, "DELETE cannot be nested" if nested_deletes.any?
327
311
 
328
- data, nested_field_paths_and_values = remove_field_value_from data
312
+ data, nested_field_paths_and_values = remove_field_value_from data
329
313
 
330
314
  field_paths_and_values = root_field_paths_and_values.merge nested_field_paths_and_values
331
315
 
@@ -338,34 +322,31 @@ module Google
338
322
  raise ArgumentError, "data is required"
339
323
  end
340
324
 
325
+ write = Google::Cloud::Firestore::V1::Write.new(
326
+ update: Google::Cloud::Firestore::V1::Document.new(name: doc_path),
327
+ update_mask: Google::Cloud::Firestore::V1::DocumentMask.new,
328
+ current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true)
329
+ )
330
+
341
331
  if data.any? || delete_paths.any?
342
- write = Google::Cloud::Firestore::V1::Write.new(
343
- update: Google::Cloud::Firestore::V1::Document.new(
344
- name: doc_path,
345
- fields: hash_to_fields(data)),
346
- update_mask: Google::Cloud::Firestore::V1::DocumentMask.new(
347
- field_paths: (field_paths).map(&:formatted_string).sort),
348
- current_document: Google::Cloud::Firestore::V1::Precondition.new(
349
- exists: true)
350
- )
332
+ htf = hash_to_fields data
333
+ htf.each_pair do |k, v|
334
+ write.update.fields[k] = v
335
+ end
336
+ write.update_mask.field_paths += field_paths.map(&:formatted_string).sort
337
+
351
338
  if update_time
352
- write.current_document = \
353
- Google::Cloud::Firestore::V1::Precondition.new(
354
- update_time: time_to_timestamp(update_time))
339
+ write.current_document = Google::Cloud::Firestore::V1::Precondition.new(
340
+ update_time: time_to_timestamp(update_time)
341
+ )
355
342
  end
356
- writes << write
357
343
  end
358
344
 
359
345
  if field_paths_and_values.any?
360
- transform_write = transform_write doc_path, field_paths_and_values
361
- if data.empty?
362
- transform_write.current_document = \
363
- Google::Cloud::Firestore::V1::Precondition.new(exists: true)
364
- end
365
- writes << transform_write
346
+ write.update_transforms += field_transforms field_paths_and_values
366
347
  end
367
348
 
368
- writes
349
+ write
369
350
  end
370
351
 
371
352
  def write_for_delete doc_path, exists: nil, update_time: nil
@@ -387,13 +368,20 @@ module Google
387
368
  write
388
369
  end
389
370
 
390
- def is_field_value_nested obj, field_value_type = nil
371
+ def field_value_nested? obj, field_value_type = nil
391
372
  return obj if obj.is_a?(FieldValue) && (field_value_type.nil? || obj.type == field_value_type)
392
373
 
393
- if obj.is_a? Array
394
- obj.each { |o| val = is_field_value_nested o, field_value_type; return val if val }
395
- elsif obj.is_a? Hash
396
- obj.each { |_k, v| val = is_field_value_nested v, field_value_type; return val if val }
374
+ case obj
375
+ when Array
376
+ obj.each do |o|
377
+ val = field_value_nested? o, field_value_type
378
+ return val if val
379
+ end
380
+ when Hash
381
+ obj.each do |_k, v|
382
+ val = field_value_nested? v, field_value_type
383
+ return val if val
384
+ end
397
385
  end
398
386
  nil
399
387
  end
@@ -406,35 +394,33 @@ module Google
406
394
  if value.is_a?(FieldValue) && (field_value_type.nil? || value.type == field_value_type)
407
395
  paths << [FieldPath.new(*key), value]
408
396
  nil # will be removed by calling compact
409
- else
410
- if value.is_a? Hash
411
- unless value.empty?
412
- nested_hash, nested_paths = remove_field_value_from value, field_value_type
413
- if nested_paths.any?
414
- nested_paths.each do |nested_field_path, nested_field_value|
415
- updated_field_paths = ([key] + nested_field_path.fields).flatten
416
- updated_field_path = FieldPath.new *updated_field_paths
417
- paths << [updated_field_path, nested_field_value]
418
- end
419
- end
420
- if nested_hash.empty?
421
- nil # will be removed by calling compact
422
- else
423
- [String(key), nested_hash]
397
+ elsif value.is_a? Hash
398
+ if value.empty?
399
+ [String(key), value]
400
+ else
401
+ nested_hash, nested_paths = remove_field_value_from value, field_value_type
402
+ if nested_paths.any?
403
+ nested_paths.each do |nested_field_path, nested_field_value|
404
+ updated_field_paths = ([key] + nested_field_path.fields).flatten
405
+ updated_field_path = FieldPath.new(*updated_field_paths)
406
+ paths << [updated_field_path, nested_field_value]
424
407
  end
408
+ end
409
+ if nested_hash.empty?
410
+ nil # will be removed by calling compact
425
411
  else
426
- [String(key), value]
412
+ [String(key), nested_hash]
427
413
  end
428
- else
429
- if value.is_a? Array
430
- nested_field_value = is_field_value_nested value, field_value_type
431
- if nested_field_value
432
- raise ArgumentError, "cannot nest #{nested_field_value.type} under arrays"
433
- end
414
+ end
415
+ else
416
+ if value.is_a? Array
417
+ nested_field_value = field_value_nested? value, field_value_type
418
+ if nested_field_value
419
+ raise ArgumentError, "cannot nest #{nested_field_value.type} under arrays"
434
420
  end
435
-
436
- [String(key), value]
437
421
  end
422
+
423
+ [String(key), value]
438
424
  end
439
425
  end
440
426
 
@@ -449,14 +435,14 @@ module Google
449
435
  if value.is_a? Hash
450
436
  nested_paths = identify_leaf_nodes value
451
437
  nested_paths.each do |nested_path|
452
- paths << (([key] + nested_path.fields).flatten)
438
+ paths << ([key] + nested_path.fields).flatten
453
439
  end
454
440
  else
455
441
  paths << [key]
456
442
  end
457
443
  end
458
444
 
459
- paths.map { |path| FieldPath.new *path }
445
+ paths.map { |path| FieldPath.new(*path) }
460
446
  end
461
447
 
462
448
  def identify_all_file_paths hash
@@ -465,15 +451,14 @@ module Google
465
451
  hash.map do |key, value|
466
452
  paths << [key]
467
453
 
468
- if value.is_a? Hash
469
- nested_paths = identify_all_file_paths value
470
- nested_paths.each do |nested_path|
471
- paths << (([key] + nested_path.fields).flatten)
472
- end
454
+ next unless value.is_a? Hash
455
+ nested_paths = identify_all_file_paths value
456
+ nested_paths.each do |nested_path|
457
+ paths << ([key] + nested_path.fields).flatten
473
458
  end
474
459
  end
475
460
 
476
- paths.map { |path| FieldPath.new *path }
461
+ paths.map { |path| FieldPath.new(*path) }
477
462
  end
478
463
 
479
464
  def select_by_field_paths hash, field_paths
@@ -533,19 +518,19 @@ module Google
533
518
  right_hash.each_pair do |key, right_value|
534
519
  left_value = left_hash[key]
535
520
 
536
- if left_value.is_a?(Hash) && right_value.is_a?(Hash)
537
- left_hash[key] = deep_merge_hashes left_value, right_value
538
- else
539
- left_hash[key] = right_value
540
- end
521
+ left_hash[key] = if left_value.is_a?(Hash) && right_value.is_a?(Hash)
522
+ deep_merge_hashes left_value, right_value
523
+ else
524
+ right_value
525
+ end
541
526
  end
542
527
 
543
528
  left_hash
544
529
  end
545
530
 
546
- START_FIELD_PATH_CHARS = /\A[a-zA-Z_]/
547
- INVALID_FIELD_PATH_CHARS = /[\~\*\/\[\]]/
548
- ESCAPED_FIELD_PATH = /\A\`(.*)\`\z/
531
+ START_FIELD_PATH_CHARS = /\A[a-zA-Z_]/.freeze
532
+ INVALID_FIELD_PATH_CHARS = %r{[~*/\[\]]}.freeze
533
+ ESCAPED_FIELD_PATH = /\A`(.*)`\z/.freeze
549
534
 
550
535
  def build_hash_from_field_paths_and_values pairs
551
536
  pairs.each do |field_path, _value|
@@ -579,59 +564,52 @@ module Google
579
564
  "`#{str}`"
580
565
  end
581
566
 
582
- def transform_write doc_path, paths
583
- field_transforms = paths.map do |field_path, field_value|
584
- to_field_transform field_path, field_value
585
- end
586
-
587
- Google::Cloud::Firestore::V1::Write.new(
588
- transform: Google::Cloud::Firestore::V1::DocumentTransform.new(
589
- document: doc_path,
590
- field_transforms: field_transforms
591
- )
592
- )
593
- end
594
-
595
567
  def to_field_transform field_path, field_value
596
- if field_value.type == :server_time
568
+ case field_value.type
569
+ when :server_time
597
570
  Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
598
- field_path: field_path.formatted_string,
571
+ field_path: field_path.formatted_string,
599
572
  set_to_server_value: :REQUEST_TIME
600
573
  )
601
- elsif field_value.type == :array_union
574
+ when :array_union
602
575
  Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
603
- field_path: field_path.formatted_string,
576
+ field_path: field_path.formatted_string,
604
577
  append_missing_elements: raw_to_value(Array(field_value.value)).array_value
605
578
  )
606
- elsif field_value.type == :array_delete
579
+ when :array_delete
607
580
  Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
608
- field_path: field_path.formatted_string,
581
+ field_path: field_path.formatted_string,
609
582
  remove_all_from_array: raw_to_value(Array(field_value.value)).array_value
610
583
  )
611
- elsif field_value.type == :increment
584
+ when :increment
612
585
  Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
613
586
  field_path: field_path.formatted_string,
614
- increment: raw_to_value(field_value.value)
587
+ increment: raw_to_value(field_value.value)
615
588
  )
616
- elsif field_value.type == :maximum
589
+ when :maximum
617
590
  Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
618
591
  field_path: field_path.formatted_string,
619
- maximum: raw_to_value(field_value.value)
592
+ maximum: raw_to_value(field_value.value)
620
593
  )
621
- elsif field_value.type == :minimum
594
+ when :minimum
622
595
  Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
623
596
  field_path: field_path.formatted_string,
624
- minimum: raw_to_value(field_value.value)
597
+ minimum: raw_to_value(field_value.value)
625
598
  )
626
599
  else
627
600
  raise ArgumentError, "unknown field transform #{field_value.type}"
628
601
  end
629
602
  end
630
603
  end
631
- # rubocop:enable all
632
604
 
633
605
  extend ClassMethods
634
606
  end
607
+ # rubocop:enable Metrics/AbcSize
608
+ # rubocop:enable Metrics/BlockLength
609
+ # rubocop:enable Metrics/CyclomaticComplexity
610
+ # rubocop:enable Metrics/MethodLength
611
+ # rubocop:enable Metrics/ModuleLength
612
+ # rubocop:enable Metrics/PerceivedComplexity
635
613
  end
636
614
  end
637
615
  end