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.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/LICENSE +201 -0
- data/README.md +30 -0
- data/lib/google-cloud-firestore.rb +106 -0
- data/lib/google/cloud/firestore.rb +514 -0
- data/lib/google/cloud/firestore/batch.rb +462 -0
- data/lib/google/cloud/firestore/client.rb +449 -0
- data/lib/google/cloud/firestore/collection_reference.rb +249 -0
- data/lib/google/cloud/firestore/commit_response.rb +145 -0
- data/lib/google/cloud/firestore/convert.rb +561 -0
- data/lib/google/cloud/firestore/credentials.rb +35 -0
- data/lib/google/cloud/firestore/document_reference.rb +468 -0
- data/lib/google/cloud/firestore/document_snapshot.rb +324 -0
- data/lib/google/cloud/firestore/field_path.rb +216 -0
- data/lib/google/cloud/firestore/field_value.rb +113 -0
- data/lib/google/cloud/firestore/generate.rb +35 -0
- data/lib/google/cloud/firestore/query.rb +651 -0
- data/lib/google/cloud/firestore/service.rb +176 -0
- data/lib/google/cloud/firestore/transaction.rb +726 -0
- data/lib/google/cloud/firestore/v1beta1.rb +121 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/common.rb +63 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/document.rb +134 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/firestore.rb +584 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/query.rb +215 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/firestore/v1beta1/write.rb +167 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/protobuf/any.rb +124 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/protobuf/timestamp.rb +106 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/protobuf/wrappers.rb +89 -0
- data/lib/google/cloud/firestore/v1beta1/doc/google/rpc/status.rb +83 -0
- data/lib/google/cloud/firestore/v1beta1/doc/overview.rb +53 -0
- data/lib/google/cloud/firestore/v1beta1/firestore_client.rb +974 -0
- data/lib/google/cloud/firestore/v1beta1/firestore_client_config.json +100 -0
- data/lib/google/cloud/firestore/version.rb +22 -0
- data/lib/google/firestore/v1beta1/common_pb.rb +44 -0
- data/lib/google/firestore/v1beta1/document_pb.rb +49 -0
- data/lib/google/firestore/v1beta1/firestore_pb.rb +219 -0
- data/lib/google/firestore/v1beta1/firestore_services_pb.rb +87 -0
- data/lib/google/firestore/v1beta1/query_pb.rb +103 -0
- data/lib/google/firestore/v1beta1/write_pb.rb +73 -0
- metadata +251 -0
@@ -0,0 +1,449 @@
|
|
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/service"
|
18
|
+
require "google/cloud/firestore/field_path"
|
19
|
+
require "google/cloud/firestore/field_value"
|
20
|
+
require "google/cloud/firestore/collection_reference"
|
21
|
+
require "google/cloud/firestore/document_reference"
|
22
|
+
require "google/cloud/firestore/document_snapshot"
|
23
|
+
require "google/cloud/firestore/batch"
|
24
|
+
require "google/cloud/firestore/transaction"
|
25
|
+
|
26
|
+
module Google
|
27
|
+
module Cloud
|
28
|
+
module Firestore
|
29
|
+
##
|
30
|
+
# # Client
|
31
|
+
#
|
32
|
+
# The Cloud Firestore Client used is to access and manipulate the
|
33
|
+
# collections and documents in the Firestore database.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# require "google/cloud/firestore"
|
37
|
+
#
|
38
|
+
# firestore = Google::Cloud::Firestore.new
|
39
|
+
#
|
40
|
+
# # Get a document reference
|
41
|
+
# nyc_ref = firestore.doc "cities/NYC"
|
42
|
+
#
|
43
|
+
# firestore.batch do |b|
|
44
|
+
# b.update(nyc_ref, { name: "New York City" })
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
class Client
|
48
|
+
##
|
49
|
+
# @private The Service object.
|
50
|
+
attr_accessor :service
|
51
|
+
|
52
|
+
##
|
53
|
+
# @private Creates a new Firestore Database instance.
|
54
|
+
def initialize service
|
55
|
+
@service = service
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# The project identifier for the Cloud Firestore database.
|
60
|
+
#
|
61
|
+
# @return [String] project identifier.
|
62
|
+
def project_id
|
63
|
+
service.project
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# The database identifier for the Cloud Firestore database.
|
68
|
+
#
|
69
|
+
# @return [String] database identifier.
|
70
|
+
def database_id
|
71
|
+
"(default)"
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# @private The full Database path for the Cloud Firestore database.
|
76
|
+
#
|
77
|
+
# @return [String] database resource path.
|
78
|
+
def path
|
79
|
+
service.database_path
|
80
|
+
end
|
81
|
+
|
82
|
+
# @!group Access
|
83
|
+
|
84
|
+
##
|
85
|
+
# Retrieves a list of collections.
|
86
|
+
#
|
87
|
+
# @yield [collections] The block for accessing the collections.
|
88
|
+
# @yieldparam [CollectionReference] collection A collection.
|
89
|
+
#
|
90
|
+
# @return [Enumerator<CollectionReference>] collection list.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# require "google/cloud/firestore"
|
94
|
+
#
|
95
|
+
# firestore = Google::Cloud::Firestore.new
|
96
|
+
#
|
97
|
+
# # Get the root collections
|
98
|
+
# firestore.cols.each do |col|
|
99
|
+
# puts col.collection_id
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
def cols
|
103
|
+
ensure_service!
|
104
|
+
|
105
|
+
return enum_for(:cols) unless block_given?
|
106
|
+
|
107
|
+
collection_ids = service.list_collections "#{path}/documents"
|
108
|
+
collection_ids.each { |collection_id| yield col(collection_id) }
|
109
|
+
end
|
110
|
+
alias_method :collections, :cols
|
111
|
+
|
112
|
+
##
|
113
|
+
# Retrieves a collection.
|
114
|
+
#
|
115
|
+
# @param [String] collection_path A string representing the path of the
|
116
|
+
# collection, relative to the document root of the database.
|
117
|
+
#
|
118
|
+
# @return [CollectionReference] A collection.
|
119
|
+
#
|
120
|
+
# @example
|
121
|
+
# require "google/cloud/firestore"
|
122
|
+
#
|
123
|
+
# firestore = Google::Cloud::Firestore.new
|
124
|
+
#
|
125
|
+
# # Get the cities collection
|
126
|
+
# cities_col = firestore.col "cities"
|
127
|
+
#
|
128
|
+
# # Get the document for NYC
|
129
|
+
# nyc_ref = cities_col.doc "NYC"
|
130
|
+
#
|
131
|
+
def col collection_path
|
132
|
+
if collection_path.to_s.split("/").count.even?
|
133
|
+
fail ArgumentError, "collection_path must refer to a collection."
|
134
|
+
end
|
135
|
+
|
136
|
+
CollectionReference.from_path \
|
137
|
+
"#{path}/documents/#{collection_path}", self
|
138
|
+
end
|
139
|
+
alias_method :collection, :col
|
140
|
+
|
141
|
+
##
|
142
|
+
# Retrieves a document reference.
|
143
|
+
#
|
144
|
+
# @param [String] document_path A string representing the path of the
|
145
|
+
# document, relative to the document root of the database.
|
146
|
+
#
|
147
|
+
# @return [DocumentReference] A document.
|
148
|
+
#
|
149
|
+
# @example
|
150
|
+
# require "google/cloud/firestore"
|
151
|
+
#
|
152
|
+
# firestore = Google::Cloud::Firestore.new
|
153
|
+
#
|
154
|
+
# # Get a document
|
155
|
+
# nyc_ref = firestore.doc "cities/NYC"
|
156
|
+
#
|
157
|
+
# puts nyc_ref.document_id
|
158
|
+
#
|
159
|
+
def doc document_path
|
160
|
+
if document_path.to_s.split("/").count.odd?
|
161
|
+
fail ArgumentError, "document_path must refer to a document."
|
162
|
+
end
|
163
|
+
|
164
|
+
doc_path = "#{path}/documents/#{document_path}"
|
165
|
+
|
166
|
+
DocumentReference.from_path doc_path, self
|
167
|
+
end
|
168
|
+
alias_method :document, :doc
|
169
|
+
|
170
|
+
##
|
171
|
+
# Retrieves a list of document snapshots.
|
172
|
+
#
|
173
|
+
# @param [String, DocumentReference] docs One or more strings
|
174
|
+
# representing the path of the document, or document reference
|
175
|
+
# objects.
|
176
|
+
#
|
177
|
+
# @yield [documents] The block for accessing the document snapshots.
|
178
|
+
# @yieldparam [DocumentSnapshot] document A document snapshot.
|
179
|
+
#
|
180
|
+
# @return [Enumerator<DocumentSnapshot>] document snapshots list.
|
181
|
+
#
|
182
|
+
# @example
|
183
|
+
# require "google/cloud/firestore"
|
184
|
+
#
|
185
|
+
# firestore = Google::Cloud::Firestore.new
|
186
|
+
#
|
187
|
+
# # Get and print city documents
|
188
|
+
# cities = ["cities/NYC", "cities/SF", "cities/LA"]
|
189
|
+
# firestore.get_all(cities).each do |city|
|
190
|
+
# puts "#{city.document_id} has #{city[:population]} residents."
|
191
|
+
# end
|
192
|
+
#
|
193
|
+
def get_all *docs
|
194
|
+
ensure_service!
|
195
|
+
|
196
|
+
return enum_for(:get_all, docs) unless block_given?
|
197
|
+
|
198
|
+
doc_paths = Array(docs).flatten.map do |doc_path|
|
199
|
+
coalesce_doc_path_argument doc_path
|
200
|
+
end
|
201
|
+
|
202
|
+
results = service.get_documents doc_paths
|
203
|
+
results.each do |result|
|
204
|
+
next if result.result.nil?
|
205
|
+
yield DocumentSnapshot.from_batch_result(result, self)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
alias_method :get_docs, :get_all
|
209
|
+
alias_method :get_documents, :get_all
|
210
|
+
alias_method :find, :get_all
|
211
|
+
|
212
|
+
##
|
213
|
+
# Creates a field path object representing the sentinel ID of a
|
214
|
+
# document. It can be used in queries to sort or filter by the document
|
215
|
+
# ID. See {Client#document_id}.
|
216
|
+
#
|
217
|
+
# @return [FieldPath] The field path object.
|
218
|
+
#
|
219
|
+
# @example
|
220
|
+
# require "google/cloud/firestore"
|
221
|
+
#
|
222
|
+
# firestore = Google::Cloud::Firestore.new
|
223
|
+
#
|
224
|
+
# # Get a collection reference
|
225
|
+
# cities_col = firestore.col "cities"
|
226
|
+
#
|
227
|
+
# # Create a query
|
228
|
+
# query = cities_col.start_at("NYC").order(
|
229
|
+
# Google::Cloud::Firestore::FieldPath.document_id
|
230
|
+
# )
|
231
|
+
#
|
232
|
+
# query.get do |city|
|
233
|
+
# puts "#{city.document_id} has #{city[:population]} residents."
|
234
|
+
# end
|
235
|
+
#
|
236
|
+
def document_id
|
237
|
+
FieldPath.document_id
|
238
|
+
end
|
239
|
+
|
240
|
+
##
|
241
|
+
# Creates a field path object representing the nested fields for
|
242
|
+
# document data.
|
243
|
+
#
|
244
|
+
# @return [Array<String>] The fields.
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# require "google/cloud/firestore"
|
248
|
+
#
|
249
|
+
# firestore = Google::Cloud::Firestore.new
|
250
|
+
#
|
251
|
+
# user_snap = firestore.doc("users/frank").get
|
252
|
+
#
|
253
|
+
# nested_field_path = firestore.field_path :favorites, :food
|
254
|
+
# user_snap.get(nested_field_path) #=> "Pizza"
|
255
|
+
#
|
256
|
+
def field_path *fields
|
257
|
+
FieldPath.new(*fields)
|
258
|
+
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# Creates a field value object representing the deletion of a field in
|
262
|
+
# document data.
|
263
|
+
#
|
264
|
+
# @return [FieldValue] The delete field value object.
|
265
|
+
#
|
266
|
+
# @example
|
267
|
+
# require "google/cloud/firestore"
|
268
|
+
#
|
269
|
+
# firestore = Google::Cloud::Firestore.new
|
270
|
+
#
|
271
|
+
# # Get a document reference
|
272
|
+
# nyc_ref = firestore.doc "cities/NYC"
|
273
|
+
#
|
274
|
+
# nyc_ref.update({ name: "New York City",
|
275
|
+
# trash: firestore.field_delete })
|
276
|
+
#
|
277
|
+
def field_delete
|
278
|
+
FieldValue.delete
|
279
|
+
end
|
280
|
+
|
281
|
+
##
|
282
|
+
# Creates a field value object representing set a field's value to
|
283
|
+
# the server timestamp when accessing the document data.
|
284
|
+
#
|
285
|
+
# @return [FieldValue] The server time field value object.
|
286
|
+
#
|
287
|
+
# @example
|
288
|
+
# require "google/cloud/firestore"
|
289
|
+
#
|
290
|
+
# firestore = Google::Cloud::Firestore.new
|
291
|
+
#
|
292
|
+
# # Get a document reference
|
293
|
+
# nyc_ref = firestore.doc "cities/NYC"
|
294
|
+
#
|
295
|
+
# nyc_ref.update({ name: "New York City",
|
296
|
+
# updated_at: firestore.field_server_time })
|
297
|
+
#
|
298
|
+
def field_server_time
|
299
|
+
FieldValue.server_time
|
300
|
+
end
|
301
|
+
|
302
|
+
# @!endgroup
|
303
|
+
|
304
|
+
# @!group Operations
|
305
|
+
|
306
|
+
##
|
307
|
+
# Perform multiple changes at the same time.
|
308
|
+
#
|
309
|
+
# All changes are accumulated in memory until the block completes.
|
310
|
+
# Unlike transactions, batches don't lock on document reads, should only
|
311
|
+
# fail if users provide preconditions, and are not automatically
|
312
|
+
# retried. See {Batch}.
|
313
|
+
#
|
314
|
+
# @see https://firebase.google.com/docs/firestore/manage-data/transactions
|
315
|
+
# Transactions and Batched Writes
|
316
|
+
#
|
317
|
+
# @yield [batch] The block for reading data and making changes.
|
318
|
+
# @yieldparam [Batch] batch The write batch object for making changes.
|
319
|
+
#
|
320
|
+
# @return [CommitResponse] The response from committing the changes.
|
321
|
+
#
|
322
|
+
# @example
|
323
|
+
# require "google/cloud/firestore"
|
324
|
+
#
|
325
|
+
# firestore = Google::Cloud::Firestore.new
|
326
|
+
#
|
327
|
+
# firestore.batch do |b|
|
328
|
+
# # Set the data for NYC
|
329
|
+
# b.set("cities/NYC", { name: "New York City" })
|
330
|
+
#
|
331
|
+
# # Update the population for SF
|
332
|
+
# b.update("cities/SF", { population: 1000000 })
|
333
|
+
#
|
334
|
+
# # Delete LA
|
335
|
+
# b.delete("cities/LA")
|
336
|
+
# end
|
337
|
+
#
|
338
|
+
def batch
|
339
|
+
batch = Batch.from_client self
|
340
|
+
yield batch
|
341
|
+
batch.commit
|
342
|
+
end
|
343
|
+
|
344
|
+
##
|
345
|
+
# Create a transaction to perform multiple reads and writes that are
|
346
|
+
# executed atomically at a single logical point in time in a database.
|
347
|
+
#
|
348
|
+
# All changes are accumulated in memory until the block completes.
|
349
|
+
# Transactions will be automatically retried when documents change
|
350
|
+
# before the transaction is committed. See {Transaction}.
|
351
|
+
#
|
352
|
+
# @see https://firebase.google.com/docs/firestore/manage-data/transactions
|
353
|
+
# Transactions and Batched Writes
|
354
|
+
#
|
355
|
+
# @param [Integer] max_retries The maximum number of retries for
|
356
|
+
# transactions failed due to errors. Default is 5. Optional.
|
357
|
+
#
|
358
|
+
# @yield [transaction] The block for reading data and making changes.
|
359
|
+
# @yieldparam [Transaction] transaction The transaction object for
|
360
|
+
# making changes.
|
361
|
+
#
|
362
|
+
# @return [CommitResponse] The response from committing the changes.
|
363
|
+
#
|
364
|
+
# @example
|
365
|
+
# require "google/cloud/firestore"
|
366
|
+
#
|
367
|
+
# firestore = Google::Cloud::Firestore.new
|
368
|
+
#
|
369
|
+
# firestore.transaction do |tx|
|
370
|
+
# # Set the data for NYC
|
371
|
+
# tx.set("cities/NYC", { name: "New York City" })
|
372
|
+
#
|
373
|
+
# # Update the population for SF
|
374
|
+
# tx.update("cities/SF", { population: 1000000 })
|
375
|
+
#
|
376
|
+
# # Delete LA
|
377
|
+
# tx.delete("cities/LA")
|
378
|
+
# end
|
379
|
+
#
|
380
|
+
def transaction max_retries: nil
|
381
|
+
max_retries = 5 unless max_retries.is_a? Integer
|
382
|
+
retries = 0
|
383
|
+
backoff = 1.0
|
384
|
+
|
385
|
+
transaction = Transaction.from_client self
|
386
|
+
begin
|
387
|
+
yield transaction
|
388
|
+
transaction.commit
|
389
|
+
rescue Google::Cloud::UnavailableError => err
|
390
|
+
# Re-raise if deadline has passed
|
391
|
+
raise err if retries >= max_retries
|
392
|
+
# Sleep with incremental backoff
|
393
|
+
sleep(backoff *= 1.3)
|
394
|
+
# Create new transaction and retry
|
395
|
+
transaction = Transaction.from_client \
|
396
|
+
self, previous_transaction: transaction.transaction_id
|
397
|
+
retries += 1
|
398
|
+
retry
|
399
|
+
rescue Google::Cloud::InvalidArgumentError => err
|
400
|
+
# Return if a previous call has succeeded
|
401
|
+
return nil if retries > 0
|
402
|
+
# Re-raise error.
|
403
|
+
raise err
|
404
|
+
rescue => err
|
405
|
+
# Rollback transaction when handling unexpected error
|
406
|
+
transaction.rollback rescue nil
|
407
|
+
# Re-raise error.
|
408
|
+
raise err
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
# @!endgroup
|
413
|
+
|
414
|
+
protected
|
415
|
+
|
416
|
+
##
|
417
|
+
# @private
|
418
|
+
def coalesce_get_argument obj
|
419
|
+
if obj.is_a?(String) || obj.is_a?(Symbol)
|
420
|
+
if obj.to_s.split("/").count.even?
|
421
|
+
return doc obj # Convert a DocumentReference
|
422
|
+
else
|
423
|
+
return col obj # Convert to Query
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
return obj.ref if obj.is_a? DocumentSnapshot
|
428
|
+
|
429
|
+
obj
|
430
|
+
end
|
431
|
+
|
432
|
+
##
|
433
|
+
# @private
|
434
|
+
def coalesce_doc_path_argument doc_path
|
435
|
+
return doc_path.path if doc_path.respond_to? :path
|
436
|
+
|
437
|
+
doc(doc_path).path
|
438
|
+
end
|
439
|
+
|
440
|
+
##
|
441
|
+
# @private Raise an error unless an active connection to the service is
|
442
|
+
# available.
|
443
|
+
def ensure_service!
|
444
|
+
fail "Must have active connection to service" unless service
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
@@ -0,0 +1,249 @@
|
|
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_reference"
|
18
|
+
require "google/cloud/firestore/document_snapshot"
|
19
|
+
require "google/cloud/firestore/query"
|
20
|
+
require "google/cloud/firestore/generate"
|
21
|
+
|
22
|
+
module Google
|
23
|
+
module Cloud
|
24
|
+
module Firestore
|
25
|
+
##
|
26
|
+
# # CollectionReference
|
27
|
+
#
|
28
|
+
# A collection reference object ise used for adding documents, getting
|
29
|
+
# document references, and querying for documents (See {Query}).
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# require "google/cloud/firestore"
|
33
|
+
#
|
34
|
+
# firestore = Google::Cloud::Firestore.new
|
35
|
+
#
|
36
|
+
# # Get a collection reference
|
37
|
+
# cities_col = firestore.col "cities"
|
38
|
+
#
|
39
|
+
# # Get and print all city documents
|
40
|
+
# cities_col.get do |city|
|
41
|
+
# puts "#{city.document_id} has #{city[:population]} residents."
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
class CollectionReference < Query
|
45
|
+
##
|
46
|
+
# @private The firestore client object.
|
47
|
+
attr_accessor :client
|
48
|
+
|
49
|
+
##
|
50
|
+
# The collection identifier for the collection resource.
|
51
|
+
#
|
52
|
+
# @return [String] collection identifier.
|
53
|
+
def collection_id
|
54
|
+
path.split("/").last
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# A string representing the path of the collection, relative to the
|
59
|
+
# document root of the database.
|
60
|
+
#
|
61
|
+
# @return [String] collection path.
|
62
|
+
def collection_path
|
63
|
+
path.split("/", 6).last
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# @private A string representing the full path of the collection
|
68
|
+
# resource.
|
69
|
+
#
|
70
|
+
# @return [String] collection resource path.
|
71
|
+
def path
|
72
|
+
@path
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# @private The parent path for the collection.
|
77
|
+
def parent_path
|
78
|
+
path.split("/")[0...-1].join("/")
|
79
|
+
end
|
80
|
+
|
81
|
+
# @!group Access
|
82
|
+
|
83
|
+
##
|
84
|
+
# Retrieves a document reference.
|
85
|
+
#
|
86
|
+
# @param [String, nil] document_path A string representing the path of
|
87
|
+
# the document, relative to the document root of the database. If a
|
88
|
+
# string is not provided, and random document identifier will be
|
89
|
+
# generated. Optional.
|
90
|
+
#
|
91
|
+
# @return [DocumentReference] A document.
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# require "google/cloud/firestore"
|
95
|
+
#
|
96
|
+
# firestore = Google::Cloud::Firestore.new
|
97
|
+
#
|
98
|
+
# # Get a collection reference
|
99
|
+
# cities_col = firestore.col "cities"
|
100
|
+
#
|
101
|
+
# # Get a document reference
|
102
|
+
# nyc_ref = cities_col.doc "NYC"
|
103
|
+
#
|
104
|
+
# # The document ID is what was provided
|
105
|
+
# nyc_ref.document_id #=> "NYC"
|
106
|
+
#
|
107
|
+
# @example Create a document reference with a random ID:
|
108
|
+
# require "google/cloud/firestore"
|
109
|
+
#
|
110
|
+
# firestore = Google::Cloud::Firestore.new
|
111
|
+
#
|
112
|
+
# # Get a collection reference
|
113
|
+
# cities_col = firestore.col "cities"
|
114
|
+
#
|
115
|
+
# # Get a document reference without specifying path
|
116
|
+
# random_ref = cities_col.doc
|
117
|
+
#
|
118
|
+
# # The document ID is randomly generated
|
119
|
+
# random_ref.document_id #=> "RANDOMID123XYZ"
|
120
|
+
#
|
121
|
+
def doc document_path = nil
|
122
|
+
document_path ||= random_document_id
|
123
|
+
|
124
|
+
ensure_client!
|
125
|
+
client.doc "#{collection_path}/#{document_path}"
|
126
|
+
end
|
127
|
+
alias_method :document, :doc
|
128
|
+
|
129
|
+
##
|
130
|
+
# The document reference or database the collection reference belongs
|
131
|
+
# to. If the collection is a root collection, it will return the
|
132
|
+
# database object. If the collection is nested under a document, it
|
133
|
+
# will return the document reference object.
|
134
|
+
#
|
135
|
+
# @return [Database, DocumentReference] parent object.
|
136
|
+
#
|
137
|
+
# @example Returns database object for root collections:
|
138
|
+
# require "google/cloud/firestore"
|
139
|
+
#
|
140
|
+
# firestore = Google::Cloud::Firestore.new
|
141
|
+
#
|
142
|
+
# # Get a collection reference
|
143
|
+
# cities_col = firestore.col "cities"
|
144
|
+
#
|
145
|
+
# # Get the document's parent collection
|
146
|
+
# database = cities_col.parent
|
147
|
+
#
|
148
|
+
# @example Returns document object for nested collections:
|
149
|
+
# require "google/cloud/firestore"
|
150
|
+
#
|
151
|
+
# firestore = Google::Cloud::Firestore.new
|
152
|
+
#
|
153
|
+
# # Get a collection reference
|
154
|
+
# precincts_ref = firestore.col "cities/NYC/precincts"
|
155
|
+
#
|
156
|
+
# # Get the document's parent collection
|
157
|
+
# nyc_ref = precincts_ref.parent
|
158
|
+
#
|
159
|
+
def parent
|
160
|
+
if collection_path.include? "/"
|
161
|
+
return DocumentReference.from_path parent_path, client
|
162
|
+
end
|
163
|
+
client
|
164
|
+
end
|
165
|
+
|
166
|
+
# @!endgroup
|
167
|
+
|
168
|
+
# @!group Modifications
|
169
|
+
|
170
|
+
##
|
171
|
+
# Create a document with random document identifier.
|
172
|
+
#
|
173
|
+
# The operation will fail if the document already exists.
|
174
|
+
#
|
175
|
+
# @param [Hash] data The document's fields and values. Optional.
|
176
|
+
#
|
177
|
+
# @return [DocumentReference] A created document.
|
178
|
+
#
|
179
|
+
# @example Create a document with a random ID:
|
180
|
+
# require "google/cloud/firestore"
|
181
|
+
#
|
182
|
+
# firestore = Google::Cloud::Firestore.new
|
183
|
+
#
|
184
|
+
# # Get a collection reference
|
185
|
+
# cities_col = firestore.col "cities"
|
186
|
+
#
|
187
|
+
# # Get a document reference without data
|
188
|
+
# random_ref = cities_col.add
|
189
|
+
#
|
190
|
+
# # The document ID is randomly generated
|
191
|
+
# random_ref.document_id #=> "RANDOMID123XYZ"
|
192
|
+
#
|
193
|
+
# @example Create a document snapshot:
|
194
|
+
# require "google/cloud/firestore"
|
195
|
+
#
|
196
|
+
# firestore = Google::Cloud::Firestore.new
|
197
|
+
#
|
198
|
+
# # Get a collection reference
|
199
|
+
# cities_col = firestore.col "cities"
|
200
|
+
#
|
201
|
+
# # Get a document snapshot
|
202
|
+
# random_ref = cities_col.add({ name: "New York City" })
|
203
|
+
#
|
204
|
+
# # The document ID is randomly generated
|
205
|
+
# random_ref.document_id #=> "RANDOMID123XYZ"
|
206
|
+
#
|
207
|
+
def add data = nil
|
208
|
+
data ||= {}
|
209
|
+
doc.tap { |d| d.create data }
|
210
|
+
end
|
211
|
+
|
212
|
+
# @!endgroup
|
213
|
+
|
214
|
+
##
|
215
|
+
# @private New Collection reference object from a path.
|
216
|
+
def self.from_path path, client
|
217
|
+
# Very important to correctly set @query on a collection object
|
218
|
+
query = StructuredQuery.new(
|
219
|
+
from: [
|
220
|
+
StructuredQuery::CollectionSelector.new(
|
221
|
+
collection_id: path.split("/").last
|
222
|
+
)
|
223
|
+
]
|
224
|
+
)
|
225
|
+
|
226
|
+
new.tap do |c|
|
227
|
+
c.client = client
|
228
|
+
c.instance_variable_set :@path, path
|
229
|
+
c.instance_variable_set :@query, query
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
protected
|
234
|
+
|
235
|
+
##
|
236
|
+
# @private
|
237
|
+
def random_document_id
|
238
|
+
Generate.unique_id
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# @private Raise an error unless an database available.
|
243
|
+
def ensure_client!
|
244
|
+
fail "Must have active connection to service" unless client
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|