google-cloud-firestore 2.1.0 → 2.5.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -0
- data/CONTRIBUTING.md +2 -2
- data/LOGGING.md +1 -1
- data/lib/google-cloud-firestore.rb +1 -0
- data/lib/google/cloud/firestore/batch.rb +3 -4
- data/lib/google/cloud/firestore/client.rb +10 -10
- data/lib/google/cloud/firestore/collection_reference_list.rb +3 -3
- data/lib/google/cloud/firestore/convert.rb +151 -173
- data/lib/google/cloud/firestore/document_listener.rb +86 -7
- data/lib/google/cloud/firestore/document_reference.rb +3 -4
- data/lib/google/cloud/firestore/document_reference/list.rb +4 -5
- data/lib/google/cloud/firestore/document_snapshot.rb +1 -2
- data/lib/google/cloud/firestore/field_path.rb +2 -2
- data/lib/google/cloud/firestore/query.rb +22 -20
- data/lib/google/cloud/firestore/query_listener.rb +82 -1
- data/lib/google/cloud/firestore/service.rb +4 -1
- data/lib/google/cloud/firestore/transaction.rb +5 -5
- data/lib/google/cloud/firestore/version.rb +1 -1
- data/lib/google/cloud/firestore/watch/inventory.rb +9 -8
- data/lib/google/cloud/firestore/watch/listener.rb +24 -17
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9faa52fed532effb0c8cb260b4159cfed65ba53a790f1c2451f5a610f46fa551
|
4
|
+
data.tar.gz: 8e2cbe9b830a1e4c46b49080cfa717a9e6e9f8901848aea6a905edd1d3234544
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94c1832275adb689e4394d03fd724dd39240eedb9fbfad132f4217ea97b1d6076cc0b8e0b846eec2a1afdf1180ffd2e981c5d5ecef12e6aaf11a04fe52460b44
|
7
|
+
data.tar.gz: c9b0c729751b0ed24ff39be1e56905da26bec6af30410e1112325482b07b888f3f1c07e60c5b1bc7bd8e90b58a710f0cb31e4a0d6181179c69d5b23267d5904f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,43 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 2.5.0 / 2021-03-10
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* Drop support for Ruby 2.4 and add support for Ruby 3.0
|
8
|
+
|
9
|
+
### 2.4.1 / 2021-01-06
|
10
|
+
|
11
|
+
#### Bug Fixes
|
12
|
+
|
13
|
+
* Replace usage of Write.transform with Write.update_transforms
|
14
|
+
|
15
|
+
### 2.4.0 / 2020-11-19
|
16
|
+
|
17
|
+
#### Features
|
18
|
+
|
19
|
+
* add support for != and NOT_IN queries
|
20
|
+
|
21
|
+
### 2.3.0 / 2020-09-30
|
22
|
+
|
23
|
+
#### Features
|
24
|
+
|
25
|
+
* Add error callbacks for listener threads
|
26
|
+
* Add DocumentListener#last_error
|
27
|
+
* Add DocumentListener#on_error
|
28
|
+
* Add QueryListener#last_error
|
29
|
+
* Add QueryListener#on_error
|
30
|
+
|
31
|
+
### 2.2.0 / 2020-09-17
|
32
|
+
|
33
|
+
#### Features
|
34
|
+
|
35
|
+
* quota_project can be set via library configuration ([#7630](https://www.github.com/googleapis/google-cloud-ruby/issues/7630))
|
36
|
+
|
37
|
+
#### Documentation
|
38
|
+
|
39
|
+
* Add snapshot query cursor sample ([#7601](https://www.github.com/googleapis/google-cloud-ruby/issues/7601))
|
40
|
+
|
3
41
|
### 2.1.0 / 2020-09-10
|
4
42
|
|
5
43
|
#### 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.
|
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
|
48
|
+
$ bundle install
|
49
49
|
```
|
50
50
|
|
51
51
|
## Console
|
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
|
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
|
@@ -125,6 +125,7 @@ Google::Cloud.configure.add_config! :firestore do |config|
|
|
125
125
|
config.add_field! :credentials, default_creds, match: [String, Hash, Google::Auth::Credentials], allow_nil: true
|
126
126
|
config.add_alias! :keyfile, :credentials
|
127
127
|
config.add_field! :scope, default_scopes, match: [String, Array]
|
128
|
+
config.add_field! :quota_project, nil, match: String
|
128
129
|
config.add_field! :timeout, nil, match: Integer
|
129
130
|
config.add_field! :emulator_host, default_emulator, match: String, allow_nil: true
|
130
131
|
config.add_field! :endpoint, "firestore.googleapis.com", match: String
|
@@ -119,7 +119,7 @@ module Google
|
|
119
119
|
|
120
120
|
doc_path = coalesce_doc_path_argument doc
|
121
121
|
|
122
|
-
@writes << Convert.
|
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.
|
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.
|
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
|
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 =>
|
637
|
+
rescue Google::Cloud::UnavailableError => e
|
638
638
|
# Re-raise if retried more than the max
|
639
|
-
raise
|
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 =>
|
652
|
+
rescue Google::Cloud::InvalidArgumentError => e
|
653
653
|
# Return if a previous call was retried but ultimately succeeded
|
654
|
-
return nil if backoff[:current]
|
654
|
+
return nil if backoff[:current].positive?
|
655
655
|
|
656
656
|
# Re-raise error.
|
657
|
-
raise
|
658
|
-
rescue StandardError =>
|
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
|
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
|
100
|
+
results.each(&block)
|
101
101
|
if request_limit
|
102
102
|
request_limit -= 1
|
103
|
-
break if request_limit
|
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
|
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:
|
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
|
104
|
-
Google::Cloud::Firestore::V1::Value.new(
|
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(
|
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:
|
144
|
-
longitude: pairs.last.last
|
149
|
+
latitude: pairs.first.last,
|
150
|
+
longitude: pairs.last.last
|
145
151
|
)
|
146
152
|
end
|
147
153
|
|
148
|
-
def
|
149
|
-
|
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
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
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
|
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?
|
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
|
-
|
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
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
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
|
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 |
|
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 |
|
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
|
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
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
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
|
-
|
354
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
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
|
-
|
410
|
-
if value.
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
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),
|
412
|
+
[String(key), nested_hash]
|
427
413
|
end
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
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 << (
|
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
|
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
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
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
|
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
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
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
|
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
|
-
|
568
|
+
case field_value.type
|
569
|
+
when :server_time
|
597
570
|
Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
|
598
|
-
field_path:
|
571
|
+
field_path: field_path.formatted_string,
|
599
572
|
set_to_server_value: :REQUEST_TIME
|
600
573
|
)
|
601
|
-
|
574
|
+
when :array_union
|
602
575
|
Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
|
603
|
-
field_path:
|
576
|
+
field_path: field_path.formatted_string,
|
604
577
|
append_missing_elements: raw_to_value(Array(field_value.value)).array_value
|
605
578
|
)
|
606
|
-
|
579
|
+
when :array_delete
|
607
580
|
Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
|
608
|
-
field_path:
|
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
|
-
|
584
|
+
when :increment
|
612
585
|
Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
|
613
586
|
field_path: field_path.formatted_string,
|
614
|
-
increment:
|
587
|
+
increment: raw_to_value(field_value.value)
|
615
588
|
)
|
616
|
-
|
589
|
+
when :maximum
|
617
590
|
Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
|
618
591
|
field_path: field_path.formatted_string,
|
619
|
-
maximum:
|
592
|
+
maximum: raw_to_value(field_value.value)
|
620
593
|
)
|
621
|
-
|
594
|
+
when :minimum
|
622
595
|
Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
|
623
596
|
field_path: field_path.formatted_string,
|
624
|
-
minimum:
|
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
|