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,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