google-cloud-firestore 0.20.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +201 -0
  4. data/README.md +30 -0
  5. data/lib/google-cloud-firestore.rb +106 -0
  6. data/lib/google/cloud/firestore.rb +514 -0
  7. data/lib/google/cloud/firestore/batch.rb +462 -0
  8. data/lib/google/cloud/firestore/client.rb +449 -0
  9. data/lib/google/cloud/firestore/collection_reference.rb +249 -0
  10. data/lib/google/cloud/firestore/commit_response.rb +145 -0
  11. data/lib/google/cloud/firestore/convert.rb +561 -0
  12. data/lib/google/cloud/firestore/credentials.rb +35 -0
  13. data/lib/google/cloud/firestore/document_reference.rb +468 -0
  14. data/lib/google/cloud/firestore/document_snapshot.rb +324 -0
  15. data/lib/google/cloud/firestore/field_path.rb +216 -0
  16. data/lib/google/cloud/firestore/field_value.rb +113 -0
  17. data/lib/google/cloud/firestore/generate.rb +35 -0
  18. data/lib/google/cloud/firestore/query.rb +651 -0
  19. data/lib/google/cloud/firestore/service.rb +176 -0
  20. data/lib/google/cloud/firestore/transaction.rb +726 -0
  21. data/lib/google/cloud/firestore/v1beta1.rb +121 -0
  22. data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/common.rb +63 -0
  23. data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/document.rb +134 -0
  24. data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/firestore.rb +584 -0
  25. data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/query.rb +215 -0
  26. data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/write.rb +167 -0
  27. data/lib/google/cloud/firestore/v1beta1/doc/google/protobuf/any.rb +124 -0
  28. data/lib/google/cloud/firestore/v1beta1/doc/google/protobuf/timestamp.rb +106 -0
  29. data/lib/google/cloud/firestore/v1beta1/doc/google/protobuf/wrappers.rb +89 -0
  30. data/lib/google/cloud/firestore/v1beta1/doc/google/rpc/status.rb +83 -0
  31. data/lib/google/cloud/firestore/v1beta1/doc/overview.rb +53 -0
  32. data/lib/google/cloud/firestore/v1beta1/firestore_client.rb +974 -0
  33. data/lib/google/cloud/firestore/v1beta1/firestore_client_config.json +100 -0
  34. data/lib/google/cloud/firestore/version.rb +22 -0
  35. data/lib/google/firestore/v1beta1/common_pb.rb +44 -0
  36. data/lib/google/firestore/v1beta1/document_pb.rb +49 -0
  37. data/lib/google/firestore/v1beta1/firestore_pb.rb +219 -0
  38. data/lib/google/firestore/v1beta1/firestore_services_pb.rb +87 -0
  39. data/lib/google/firestore/v1beta1/query_pb.rb +103 -0
  40. data/lib/google/firestore/v1beta1/write_pb.rb +73 -0
  41. metadata +251 -0
@@ -0,0 +1,462 @@
1
+ # Copyright 2017 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/cloud/firestore/v1beta1"
17
+ require "google/cloud/firestore/collection_reference"
18
+ require "google/cloud/firestore/document_reference"
19
+ require "google/cloud/firestore/document_snapshot"
20
+ require "google/cloud/firestore/commit_response"
21
+ require "google/cloud/firestore/convert"
22
+
23
+ module Google
24
+ module Cloud
25
+ module Firestore
26
+ ##
27
+ # # Batch
28
+ #
29
+ # A batch in Cloud Firestore is a set of writes that execute
30
+ # atomically at a single logical point in time in a database.
31
+ #
32
+ # All changes are accumulated in memory until the block passed to
33
+ # {Database#batch} completes. Unlike transactions, batches don't lock on
34
+ # document reads, should only fail if users provide preconditions, and are
35
+ # not automatically retried.
36
+ #
37
+ # @see https://firebase.google.com/docs/firestore/manage-data/transactions
38
+ # Transactions and Batched Writes
39
+ #
40
+ # @example
41
+ # require "google/cloud/firestore"
42
+ #
43
+ # firestore = Google::Cloud::Firestore.new
44
+ #
45
+ # firestore.batch do |b|
46
+ # # Set the data for NYC
47
+ # b.set("cities/NYC", { name: "New York City" })
48
+ #
49
+ # # Update the population for SF
50
+ # b.update("cities/SF", { population: 1000000 })
51
+ #
52
+ # # Delete LA
53
+ # b.delete("cities/LA")
54
+ # end
55
+ #
56
+ class Batch
57
+ ##
58
+ # @private New Batch object.
59
+ def initialize
60
+ @writes = []
61
+ end
62
+
63
+ ##
64
+ # The client the Cloud Firestore batch belongs to.
65
+ #
66
+ # @return [Client] firestore client.
67
+ def firestore
68
+ @client
69
+ end
70
+ alias_method :client, :firestore
71
+
72
+ # @!group Modifications
73
+
74
+ ##
75
+ # Create a document with the provided data (fields and values).
76
+ #
77
+ # The batch will fail if the document already exists.
78
+ #
79
+ # @param [String, DocumentReference] doc A string representing the
80
+ # path of the document, or a document reference object.
81
+ # @param [Hash] data The document's fields and values.
82
+ #
83
+ # @example Create a document using a document path:
84
+ # require "google/cloud/firestore"
85
+ #
86
+ # firestore = Google::Cloud::Firestore.new
87
+ #
88
+ # firestore.batch do |b|
89
+ # b.create("cities/NYC", { name: "New York City" })
90
+ # end
91
+ #
92
+ # @example Create a document using a document reference:
93
+ # require "google/cloud/firestore"
94
+ #
95
+ # firestore = Google::Cloud::Firestore.new
96
+ #
97
+ # # Get a document reference
98
+ # nyc_ref = firestore.doc "cities/NYC"
99
+ #
100
+ # firestore.batch do |b|
101
+ # b.create(nyc_ref, { name: "New York City" })
102
+ # end
103
+ #
104
+ # @example Create a document and set a field to server_time:
105
+ # require "google/cloud/firestore"
106
+ #
107
+ # firestore = Google::Cloud::Firestore.new
108
+ #
109
+ # # Get a document reference
110
+ # nyc_ref = firestore.doc "cities/NYC"
111
+ #
112
+ # firestore.batch do |b|
113
+ # b.create(nyc_ref, { name: "New York City",
114
+ # updated_at: firestore.field_server_time })
115
+ # end
116
+ #
117
+ def create doc, data
118
+ ensure_not_closed!
119
+
120
+ doc_path = coalesce_doc_path_argument doc
121
+
122
+ @writes << Convert.writes_for_create(doc_path, data)
123
+
124
+ nil
125
+ end
126
+
127
+ ##
128
+ # Write the provided data (fields and values) to the provided document.
129
+ # If the document does not exist, it will be created. By default, the
130
+ # provided data overwrites existing data, but the provided data can be
131
+ # merged into the existing document using the `merge` argument.
132
+ #
133
+ # If you're not sure whether the document exists, use the `merge`
134
+ # argument to merge the new data with any existing document data to
135
+ # avoid overwriting entire documents.
136
+ #
137
+ # @param [String, DocumentReference] doc A string representing the
138
+ # path of the document, or a document reference object.
139
+ # @param [Hash] data The document's fields and values.
140
+ # @param [Boolean, FieldPath, String, Symbol] merge When
141
+ # `true`, all provided data is merged with the existing document data.
142
+ # When the argument is one or more field path, only the data for
143
+ # fields in this argument is merged with the existing document data.
144
+ # The default is to not merge, but to instead overwrite the existing
145
+ # document data.
146
+ #
147
+ # @example Set a document using a document path:
148
+ # require "google/cloud/firestore"
149
+ #
150
+ # firestore = Google::Cloud::Firestore.new
151
+ #
152
+ # firestore.batch do |b|
153
+ # b.set("cities/NYC", { name: "New York City" })
154
+ # end
155
+ #
156
+ # @example Create a document using a document reference:
157
+ # require "google/cloud/firestore"
158
+ #
159
+ # firestore = Google::Cloud::Firestore.new
160
+ #
161
+ # # Get a document reference
162
+ # nyc_ref = firestore.doc "cities/NYC"
163
+ #
164
+ # firestore.batch do |b|
165
+ # b.set(nyc_ref, { name: "New York City" })
166
+ # end
167
+ #
168
+ # @example Set a document and merge all data:
169
+ # require "google/cloud/firestore"
170
+ #
171
+ # firestore = Google::Cloud::Firestore.new
172
+ #
173
+ # firestore.batch do |b|
174
+ # b.set("cities/NYC", { name: "New York City" }, merge: true)
175
+ # end
176
+ #
177
+ # @example Set a document and merge only name:
178
+ # require "google/cloud/firestore"
179
+ #
180
+ # firestore = Google::Cloud::Firestore.new
181
+ #
182
+ # firestore.batch do |b|
183
+ # b.set("cities/NYC", { name: "New York City" }, merge: :name)
184
+ # end
185
+ #
186
+ # @example Set a document and deleting a field using merge:
187
+ # require "google/cloud/firestore"
188
+ #
189
+ # firestore = Google::Cloud::Firestore.new
190
+ #
191
+ # # Get a document reference
192
+ # nyc_ref = firestore.doc "cities/NYC"
193
+ #
194
+ # nyc_data = { name: "New York City",
195
+ # trash: firestore.field_delete }
196
+ #
197
+ # firestore.batch do |b|
198
+ # b.set(nyc_ref, nyc_data, merge: true)
199
+ # end
200
+ #
201
+ # @example Set a document and set a field to server_time:
202
+ # require "google/cloud/firestore"
203
+ #
204
+ # firestore = Google::Cloud::Firestore.new
205
+ #
206
+ # # Get a document reference
207
+ # nyc_ref = firestore.doc "cities/NYC"
208
+ #
209
+ # nyc_data = { name: "New York City",
210
+ # updated_at: firestore.field_server_time }
211
+ #
212
+ # firestore.batch do |b|
213
+ # b.set(nyc_ref, nyc_data, merge: true)
214
+ # end
215
+ #
216
+ def set doc, data, merge: nil
217
+ ensure_not_closed!
218
+
219
+ doc_path = coalesce_doc_path_argument doc
220
+
221
+ @writes << Convert.writes_for_set(doc_path, data, merge: merge)
222
+
223
+ nil
224
+ end
225
+
226
+ ##
227
+ # Update the document with the provided data (fields and values). The
228
+ # provided data is merged into the existing document data.
229
+ #
230
+ # The batch will fail if the document does not exist.
231
+ #
232
+ # @param [String, DocumentReference] doc A string representing the
233
+ # path of the document, or a document reference object.
234
+ # @param [Hash<FieldPath|String|Symbol, Object>] data The document's
235
+ # fields and values.
236
+ #
237
+ # The top-level keys in the data hash are considered field paths, and
238
+ # can either be a FieldPath object, or a string representing the
239
+ # nested fields. In other words the string represents individual
240
+ # fields joined by ".". Fields containing `~`, `*`, `/`, `[`, `]`, and
241
+ # `.` cannot be in a dotted string, and should provided using a
242
+ # {FieldPath} object instead.
243
+ # @param [Time] update_time When set, the document must have been last
244
+ # updated at that time. Optional.
245
+ #
246
+ # @example Update a document using a document path:
247
+ # require "google/cloud/firestore"
248
+ #
249
+ # firestore = Google::Cloud::Firestore.new
250
+ #
251
+ # firestore.batch do |b|
252
+ # b.update("cities/NYC", { name: "New York City" })
253
+ # end
254
+ #
255
+ # @example Directly update a deeply-nested field with a `FieldPath`:
256
+ # require "google/cloud/firestore"
257
+ #
258
+ # firestore = Google::Cloud::Firestore.new
259
+ #
260
+ # nested_field_path = Google::Cloud::Firestore::FieldPath.new(
261
+ # :favorites, :food
262
+ # )
263
+ #
264
+ # firestore.batch do |b|
265
+ # b.update("users/frank", { nested_field_path: "Pasta" })
266
+ # end
267
+ #
268
+ # @example Update a document using a document reference:
269
+ # require "google/cloud/firestore"
270
+ #
271
+ # firestore = Google::Cloud::Firestore.new
272
+ #
273
+ # # Get a document reference
274
+ # nyc_ref = firestore.doc "cities/NYC"
275
+ #
276
+ # firestore.batch do |b|
277
+ # b.update(nyc_ref, { name: "New York City" })
278
+ # end
279
+ #
280
+ # @example Update a document using the `update_time` precondition:
281
+ # require "google/cloud/firestore"
282
+ #
283
+ # firestore = Google::Cloud::Firestore.new
284
+ #
285
+ # last_updated_at = Time.now - 42 # 42 seconds ago
286
+ #
287
+ # firestore.batch do |b|
288
+ # b.update("cities/NYC", { name: "New York City" },
289
+ # update_time: last_updated_at)
290
+ # end
291
+ #
292
+ # @example Update a document and deleting a field:
293
+ # require "google/cloud/firestore"
294
+ #
295
+ # firestore = Google::Cloud::Firestore.new
296
+ #
297
+ # # Get a document reference
298
+ # nyc_ref = firestore.doc "cities/NYC"
299
+ #
300
+ # nyc_data = { name: "New York City",
301
+ # trash: firestore.field_delete }
302
+ #
303
+ # firestore.batch do |b|
304
+ # b.update(nyc_ref, nyc_data)
305
+ # end
306
+ #
307
+ # @example Update a document and set a field to server_time:
308
+ # require "google/cloud/firestore"
309
+ #
310
+ # firestore = Google::Cloud::Firestore.new
311
+ #
312
+ # # Get a document reference
313
+ # nyc_ref = firestore.doc "cities/NYC"
314
+ #
315
+ # nyc_data = { name: "New York City",
316
+ # updated_at: firestore.field_server_time }
317
+ #
318
+ # firestore.batch do |b|
319
+ # b.update(nyc_ref, nyc_data)
320
+ # end
321
+ #
322
+ def update doc, data, update_time: nil
323
+ ensure_not_closed!
324
+
325
+ doc_path = coalesce_doc_path_argument doc
326
+
327
+ @writes << Convert.writes_for_update(doc_path, data,
328
+ update_time: update_time)
329
+
330
+ nil
331
+ end
332
+
333
+ ##
334
+ # Deletes a document from the database.
335
+ #
336
+ # @param [String, DocumentReference] doc A string representing the
337
+ # path of the document, or a document reference object.
338
+ # @param [Boolean] exists Whether the document must exist. When `true`,
339
+ # the document must exist or an error is raised. Default is `false`.
340
+ # Optional.
341
+ # @param [Time] update_time When set, the document must have been last
342
+ # updated at that time. Optional.
343
+ #
344
+ # @example Delete a document using a document path:
345
+ # require "google/cloud/firestore"
346
+ #
347
+ # firestore = Google::Cloud::Firestore.new
348
+ #
349
+ # firestore.batch do |b|
350
+ # b.delete "cities/NYC"
351
+ # end
352
+ #
353
+ # @example Delete a document using a document reference:
354
+ # require "google/cloud/firestore"
355
+ #
356
+ # firestore = Google::Cloud::Firestore.new
357
+ #
358
+ # # Get a document reference
359
+ # nyc_ref = firestore.doc "cities/NYC"
360
+ #
361
+ # firestore.batch do |b|
362
+ # b.delete nyc_ref
363
+ # end
364
+ #
365
+ # @example Delete a document using `exists`:
366
+ # require "google/cloud/firestore"
367
+ #
368
+ # firestore = Google::Cloud::Firestore.new
369
+ #
370
+ # firestore.batch do |b|
371
+ # b.delete "cities/NYC", exists: true
372
+ # end
373
+ #
374
+ # @example Delete a document using the `update_time` precondition:
375
+ # require "google/cloud/firestore"
376
+ #
377
+ # firestore = Google::Cloud::Firestore.new
378
+ #
379
+ # last_updated_at = Time.now - 42 # 42 seconds ago
380
+ #
381
+ # firestore.batch do |b|
382
+ # b.delete "cities/NYC", update_time: last_updated_at
383
+ # end
384
+ #
385
+ def delete doc, exists: nil, update_time: nil
386
+ ensure_not_closed!
387
+
388
+ doc_path = coalesce_doc_path_argument doc
389
+
390
+ @writes << Convert.write_for_delete(
391
+ doc_path, exists: exists, update_time: update_time)
392
+
393
+ nil
394
+ end
395
+
396
+ # @!endgroup
397
+
398
+ ##
399
+ # @private commit the batch
400
+ def commit
401
+ ensure_not_closed!
402
+ @closed = true
403
+ return nil if @writes.empty?
404
+ resp = service.commit @writes.flatten
405
+ return nil if resp.nil?
406
+ CommitResponse.from_grpc resp, @writes
407
+ end
408
+
409
+ ##
410
+ # @private the batch is complete and closed
411
+ def closed?
412
+ @closed
413
+ end
414
+
415
+ ##
416
+ # @private New Batch reference object from a path.
417
+ def self.from_client client
418
+ new.tap do |b|
419
+ b.instance_variable_set :@client, client
420
+ end
421
+ end
422
+
423
+ ##
424
+ # @private The Service object.
425
+ def service
426
+ ensure_client!
427
+
428
+ firestore.service
429
+ end
430
+
431
+ protected
432
+
433
+ ##
434
+ # @private
435
+ def coalesce_doc_path_argument doc_path
436
+ return doc_path.path if doc_path.respond_to? :path
437
+
438
+ client.doc(doc_path).path
439
+ end
440
+
441
+ ##
442
+ # @private
443
+ def ensure_not_closed!
444
+ fail "batch is closed" if closed?
445
+ end
446
+
447
+ ##
448
+ # @private Raise an error unless an database available.
449
+ def ensure_client!
450
+ fail "Must have active connection to service" unless firestore
451
+ end
452
+
453
+ ##
454
+ # @private Raise an error unless an active connection to the service
455
+ # is available.
456
+ def ensure_service!
457
+ fail "Must have active connection to service" unless service
458
+ end
459
+ end
460
+ end
461
+ end
462
+ end