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,35 @@
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 "googleauth"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Firestore
21
+ ##
22
+ # @private Represents the OAuth 2.0 signing logic for Firestore.
23
+ class Credentials < Google::Auth::Credentials
24
+ SCOPE = ["https://www.googleapis.com/auth/datastore"]
25
+ PATH_ENV_VARS = %w(FIRESTORE_CREDENTIALS FIRESTORE_KEYFILE
26
+ GOOGLE_CLOUD_CREDENTIALS GOOGLE_CLOUD_KEYFILE
27
+ GCLOUD_KEYFILE)
28
+ JSON_ENV_VARS = %w(FIRESTORE_CREDENTIALS_JSON FIRESTORE_KEYFILE_JSON
29
+ GOOGLE_CLOUD_CREDENTIALS_JSON
30
+ GOOGLE_CLOUD_KEYFILE_JSON
31
+ GCLOUD_KEYFILE_JSON)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,468 @@
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/document_snapshot"
18
+ require "google/cloud/firestore/collection_reference"
19
+
20
+ module Google
21
+ module Cloud
22
+ module Firestore
23
+ ##
24
+ # # DocumentReference
25
+ #
26
+ # A document reference object refers to a document location in a Cloud
27
+ # Firestore database and can be used to write or read data. A document
28
+ # resource at the referenced location may or may not exist.
29
+ #
30
+ # @example
31
+ # require "google/cloud/firestore"
32
+ #
33
+ # firestore = Google::Cloud::Firestore.new
34
+ #
35
+ # # Get a document reference
36
+ # nyc_ref = firestore.doc "cities/NYC"
37
+ #
38
+ class DocumentReference
39
+ ##
40
+ # @private The firestore client object.
41
+ attr_accessor :client
42
+
43
+ ##
44
+ # The document identifier for the document resource.
45
+ #
46
+ # @return [String] document identifier.
47
+ def document_id
48
+ path.split("/").last
49
+ end
50
+
51
+ ##
52
+ # A string representing the path of the document, relative to the
53
+ # document root of the database.
54
+ #
55
+ # @return [String] document path.
56
+ def document_path
57
+ path.split("/", 6).last
58
+ end
59
+
60
+ ##
61
+ # @private A string representing the full path of the document resource.
62
+ #
63
+ # @return [String] document resource path.
64
+ def path
65
+ @path
66
+ end
67
+
68
+ # @!group Access
69
+
70
+ ##
71
+ # Retrieves a list of collections nested under the document snapshot.
72
+ #
73
+ # @yield [collections] The block for accessing the collections.
74
+ # @yieldparam [CollectionReference] collection A collection.
75
+ #
76
+ # @return [Enumerator<CollectionReference>] collection list.
77
+ #
78
+ # @example
79
+ # require "google/cloud/firestore"
80
+ #
81
+ # firestore = Google::Cloud::Firestore.new
82
+ #
83
+ # # Get a document reference
84
+ # nyc_ref = firestore.doc "cities/NYC"
85
+ #
86
+ # nyc_ref.cols.each do |col|
87
+ # puts col.collection_id
88
+ # end
89
+ #
90
+ def cols
91
+ ensure_service!
92
+
93
+ return enum_for(:cols) unless block_given?
94
+
95
+ collection_ids = service.list_collections path
96
+ collection_ids.each { |collection_id| yield col(collection_id) }
97
+ end
98
+ alias_method :collections, :cols
99
+
100
+ ##
101
+ # Retrieves a collection nested under the document snapshot.
102
+ #
103
+ # @param [String] collection_path A string representing the path of
104
+ # the collection, relative to the document.
105
+ #
106
+ # @return [CollectionReference] A collection.
107
+ #
108
+ # @example
109
+ # require "google/cloud/firestore"
110
+ #
111
+ # firestore = Google::Cloud::Firestore.new
112
+ #
113
+ # # Get a document reference
114
+ # nyc_ref = firestore.doc "cities/NYC"
115
+ #
116
+ # # Get precincts sub-collection
117
+ # precincts_col = nyc_ref.col "precincts"
118
+ #
119
+ def col collection_path
120
+ if collection_path.to_s.split("/").count.even?
121
+ fail ArgumentError, "collection_path must refer to a collection."
122
+ end
123
+
124
+ CollectionReference.from_path "#{path}/#{collection_path}", client
125
+ end
126
+ alias_method :collection, :col
127
+
128
+ ##
129
+ # Retrieve the document data.
130
+ #
131
+ # @return [DocumentSnapshot] document snapshot.
132
+ #
133
+ # @example
134
+ # require "google/cloud/firestore"
135
+ #
136
+ # firestore = Google::Cloud::Firestore.new
137
+ #
138
+ # # Get a document reference
139
+ # nyc_ref = firestore.doc "cities/NYC"
140
+ #
141
+ # nyc_snap = nyc_ref.get
142
+ # nyc_snap[:population] #=> 1000000
143
+ #
144
+ def get
145
+ ensure_client!
146
+
147
+ client.get_all([self]).first
148
+ end
149
+
150
+ ##
151
+ # The collection the document reference belongs to.
152
+ #
153
+ # @return [CollectionReference] parent collection.
154
+ #
155
+ # @example
156
+ # require "google/cloud/firestore"
157
+ #
158
+ # firestore = Google::Cloud::Firestore.new
159
+ #
160
+ # # Get a document reference
161
+ # nyc_ref = firestore.doc "cities/NYC"
162
+ #
163
+ # cities_col = nyc_ref.parent
164
+ #
165
+ def parent
166
+ CollectionReference.from_path parent_path, client
167
+ end
168
+
169
+ # @!endgroup
170
+
171
+ # @!group Modifications
172
+
173
+ ##
174
+ # Create a document with the provided data (fields and values).
175
+ #
176
+ # The operation will fail if the document already exists.
177
+ #
178
+ # @param [Hash] data The document's fields and values.
179
+ #
180
+ # @return [CommitResponse::WriteResult] The result of the change.
181
+ #
182
+ # @example
183
+ # require "google/cloud/firestore"
184
+ #
185
+ # firestore = Google::Cloud::Firestore.new
186
+ #
187
+ # # Get a document reference
188
+ # nyc_ref = firestore.doc "cities/NYC"
189
+ #
190
+ # nyc_ref.create({ name: "New York City" })
191
+ #
192
+ # @example Create a document and set a field to server_time:
193
+ # require "google/cloud/firestore"
194
+ #
195
+ # firestore = Google::Cloud::Firestore.new
196
+ #
197
+ # # Get a document reference
198
+ # nyc_ref = firestore.doc "cities/NYC"
199
+ #
200
+ # nyc_ref.create({ name: "New York City",
201
+ # updated_at: firestore.field_server_time })
202
+ #
203
+ def create data
204
+ ensure_client!
205
+
206
+ resp = client.batch { |b| b.create self, data }
207
+ resp.write_results.first
208
+ end
209
+
210
+ ##
211
+ # Write the provided data (fields and values) to the document. If the
212
+ # document does not exist, it will be created. By default, the provided
213
+ # data overwrites existing data, but the provided data can be merged
214
+ # into the existing document using the `merge` argument.
215
+ #
216
+ # If you're not sure whether the document exists, use the `merge`
217
+ # argument to merge the new data with any existing document data to
218
+ # avoid overwriting entire documents.
219
+ #
220
+ # @param [Hash] data The document's fields and values.
221
+ # @param [Boolean, FieldPath, String, Symbol] merge When
222
+ # `true`, all provided data is merged with the existing document data.
223
+ # When the argument is one or more field path, only the data for
224
+ # fields in this argument is merged with the existing document data.
225
+ # The default is to not merge, but to instead overwrite the existing
226
+ # document data.
227
+ #
228
+ # @return [CommitResponse::WriteResult] The result of the change.
229
+ #
230
+ # @example
231
+ # require "google/cloud/firestore"
232
+ #
233
+ # firestore = Google::Cloud::Firestore.new
234
+ #
235
+ # # Get a document reference
236
+ # nyc_ref = firestore.doc "cities/NYC"
237
+ #
238
+ # nyc_ref.set({ name: "New York City" })
239
+ #
240
+ # @example Set a document and merge all data:
241
+ # require "google/cloud/firestore"
242
+ #
243
+ # firestore = Google::Cloud::Firestore.new
244
+ #
245
+ # # Get a document reference
246
+ # nyc_ref = firestore.doc "cities/NYC"
247
+ #
248
+ # nyc_ref.set({ name: "New York City" }, merge: true)
249
+ #
250
+ # @example Set a document and merge only name:
251
+ # require "google/cloud/firestore"
252
+ #
253
+ # firestore = Google::Cloud::Firestore.new
254
+ #
255
+ # # Get a document reference
256
+ # nyc_ref = firestore.doc "cities/NYC"
257
+ #
258
+ # nyc_ref.set({ name: "New York City" }, merge: :name)
259
+ #
260
+ # @example Set a document and deleting a field using merge:
261
+ # require "google/cloud/firestore"
262
+ #
263
+ # firestore = Google::Cloud::Firestore.new
264
+ #
265
+ # # Get a document reference
266
+ # nyc_ref = firestore.doc "cities/NYC"
267
+ #
268
+ # nyc_ref.set({ name: "New York City",
269
+ # trash: firestore.field_delete }, merge: true)
270
+ #
271
+ # @example Set a document and set a field to server_time:
272
+ # require "google/cloud/firestore"
273
+ #
274
+ # firestore = Google::Cloud::Firestore.new
275
+ #
276
+ # # Get a document reference
277
+ # nyc_ref = firestore.doc "cities/NYC"
278
+ #
279
+ # nyc_ref.set({ name: "New York City",
280
+ # updated_at: firestore.field_server_time })
281
+ #
282
+ def set data, merge: nil
283
+ ensure_client!
284
+
285
+ resp = client.batch { |b| b.set self, data, merge: merge }
286
+ resp.write_results.first
287
+ end
288
+
289
+ ##
290
+ # Update the document with the provided data (fields and values). The
291
+ # provided data is merged into the existing document data.
292
+ #
293
+ # The operation will fail if the document does not exist.
294
+ #
295
+ # @param [Hash<FieldPath|String|Symbol, Object>] data The document's
296
+ # fields and values.
297
+ #
298
+ # The top-level keys in the data hash are considered field paths, and
299
+ # can either be a FieldPath object, or a string representing the
300
+ # nested fields. In other words the string represents individual
301
+ # fields joined by ".". Fields containing `~`, `*`, `/`, `[`, `]`, and
302
+ # `.` cannot be in a dotted string, and should provided using a
303
+ # {FieldPath} object instead.
304
+ # @param [Time] update_time When set, the document must have been last
305
+ # updated at that time. Optional.
306
+ #
307
+ # @return [CommitResponse::WriteResult] The result of the change.
308
+ #
309
+ # @example
310
+ # require "google/cloud/firestore"
311
+ #
312
+ # firestore = Google::Cloud::Firestore.new
313
+ #
314
+ # # Get a document reference
315
+ # nyc_ref = firestore.doc "cities/NYC"
316
+ #
317
+ # nyc_ref.update({ name: "New York City" })
318
+ #
319
+ # @example Directly update a deeply-nested field with a `FieldPath`:
320
+ # require "google/cloud/firestore"
321
+ #
322
+ # firestore = Google::Cloud::Firestore.new
323
+ #
324
+ # user_ref = firestore.doc "users/frank"
325
+ #
326
+ # nested_field_path = Google::Cloud::Firestore::FieldPath.new(
327
+ # :favorites, :food
328
+ # )
329
+ # user_ref.update({ nested_field_path: "Pasta" })
330
+ #
331
+ # @example Update a document using the `update_time` precondition:
332
+ # require "google/cloud/firestore"
333
+ #
334
+ # firestore = Google::Cloud::Firestore.new
335
+ #
336
+ # # Get a document reference
337
+ # nyc_ref = firestore.doc "cities/NYC"
338
+ #
339
+ # last_updated_at = Time.now - 42 # 42 seconds ago
340
+ #
341
+ # nyc_ref.update({ name: "New York City" },
342
+ # update_time: last_updated_at)
343
+ #
344
+ # @example Update a document and deleting a field:
345
+ # require "google/cloud/firestore"
346
+ #
347
+ # firestore = Google::Cloud::Firestore.new
348
+ #
349
+ # # Get a document reference
350
+ # nyc_ref = firestore.doc "cities/NYC"
351
+ #
352
+ # nyc_ref.update({ name: "New York City",
353
+ # trash: firestore.field_delete })
354
+ #
355
+ # @example Update a document and set a field to server_time:
356
+ # require "google/cloud/firestore"
357
+ #
358
+ # firestore = Google::Cloud::Firestore.new
359
+ #
360
+ # # Get a document reference
361
+ # nyc_ref = firestore.doc "cities/NYC"
362
+ #
363
+ # nyc_ref.update({ name: "New York City",
364
+ # updated_at: firestore.field_server_time })
365
+ #
366
+ def update data, update_time: nil
367
+ ensure_client!
368
+
369
+ resp = client.batch do |b|
370
+ b.update self, data, update_time: update_time
371
+ end
372
+ resp.write_results.first
373
+ end
374
+
375
+ ##
376
+ # Deletes a document from the database.
377
+ #
378
+ # @param [Boolean] exists Whether the document must exist. When `true`,
379
+ # the document must exist or an error is raised. Default is `false`.
380
+ # Optional.
381
+ # @param [Time] update_time When set, the document must have been last
382
+ # updated at that time. Optional.
383
+ #
384
+ # @return [CommitResponse::WriteResult] The result of the change.
385
+ #
386
+ # @example
387
+ # require "google/cloud/firestore"
388
+ #
389
+ # firestore = Google::Cloud::Firestore.new
390
+ #
391
+ # # Get a document reference
392
+ # nyc_ref = firestore.doc "cities/NYC"
393
+ #
394
+ # nyc_ref.delete
395
+ #
396
+ # @example Delete a document using `exists`:
397
+ # require "google/cloud/firestore"
398
+ #
399
+ # firestore = Google::Cloud::Firestore.new
400
+ #
401
+ # # Get a document reference
402
+ # nyc_ref = firestore.doc "cities/NYC"
403
+ #
404
+ # nyc_ref.delete exists: true
405
+ #
406
+ # @example Delete a document using the `update_time` precondition:
407
+ # require "google/cloud/firestore"
408
+ #
409
+ # firestore = Google::Cloud::Firestore.new
410
+ #
411
+ # # Get a document reference
412
+ # nyc_ref = firestore.doc "cities/NYC"
413
+ #
414
+ # last_updated_at = Time.now - 42 # 42 seconds ago
415
+ # nyc_ref.delete update_time: last_updated_at
416
+ #
417
+ def delete exists: nil, update_time: nil
418
+ ensure_client!
419
+
420
+ resp = client.batch do |b|
421
+ b.delete self, exists: exists, update_time: update_time
422
+ end
423
+ resp.write_results.first
424
+ end
425
+
426
+ # @!endgroup
427
+
428
+ ##
429
+ # @private New DocumentReference object from a path.
430
+ def self.from_path path, client
431
+ new.tap do |r|
432
+ r.client = client
433
+ r.instance_variable_set :@path, path
434
+ end
435
+ end
436
+
437
+ protected
438
+
439
+ ##
440
+ # @private
441
+ def parent_path
442
+ path.split("/")[0...-1].join("/")
443
+ end
444
+
445
+ ##
446
+ # @private The client's Service object.
447
+ def service
448
+ ensure_client!
449
+
450
+ client.service
451
+ end
452
+
453
+ ##
454
+ # @private Raise an error unless an database available.
455
+ def ensure_client!
456
+ fail "Must have active connection to service" unless client
457
+ end
458
+
459
+ ##
460
+ # @private Raise an error unless an active connection to the service
461
+ # is available.
462
+ def ensure_service!
463
+ fail "Must have active connection to service" unless service
464
+ end
465
+ end
466
+ end
467
+ end
468
+ end