google-cloud-firestore 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
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