Skip to content

Commit bb6acb8

Browse files
authored
chore(firestore): Add query watch samples
closes: googleapis#7595 pr: googleapis#7602
1 parent c0d1e79 commit bb6acb8

3 files changed

Lines changed: 267 additions & 0 deletions

File tree

google-cloud-firestore/samples/.rubocop.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ inherit_gem:
44
Metrics/AbcSize:
55
Exclude:
66
- "query_data.rb"
7+
- "query_watch.rb"
78
Metrics/BlockLength:
89
Exclude:
910
- "acceptance/*.rb"
@@ -12,6 +13,7 @@ Metrics/MethodLength:
1213
Exclude:
1314
- "get_data.rb"
1415
- "query_data.rb"
16+
- "query_watch.rb"
1517
Naming/AccessorMethodName:
1618
Exclude:
1719
- "add_data.rb"
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright 2020 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+
# http://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+
require_relative "helper.rb"
16+
require_relative "../query_watch.rb"
17+
18+
describe "Google Cloud Firestore API samples - Query Data" do
19+
before do
20+
@firestore_project = ENV["FIRESTORE_PROJECT"]
21+
@collection_path = random_name "cities"
22+
end
23+
24+
after do
25+
delete_collection_test collection_name: @collection_path, project_id: @firestore_project
26+
end
27+
28+
it "listen_document" do
29+
document_path = random_name "SF"
30+
31+
out, _err = capture_io do
32+
listen_document project_id: @firestore_project, collection_path: @collection_path, document_path: document_path
33+
end
34+
35+
assert_includes out, "Received document snapshot: #{document_path}"
36+
end
37+
38+
it "listen_changes" do
39+
out, _err = capture_io do
40+
listen_changes project_id: @firestore_project, collection_path: @collection_path
41+
end
42+
assert_includes out, "Callback received query snapshot."
43+
assert_includes out, "Current cities in California:"
44+
assert_includes out, "New city: MTV"
45+
assert_includes out, "Modified city: MTV"
46+
assert_includes out, "Removed city: MTV"
47+
end
48+
49+
it "listen_errors" do
50+
out, err = capture_io do
51+
listen_errors project_id: @firestore_project, collection_path: @collection_path
52+
end
53+
assert_empty out
54+
assert_empty err
55+
end
56+
57+
it "listen_multiple" do
58+
out, _err = capture_io do
59+
listen_multiple project_id: @firestore_project, collection_path: @collection_path
60+
end
61+
assert_includes out, "Callback received query snapshot."
62+
assert_includes out, "Current cities in California:"
63+
assert_includes out, "SF"
64+
end
65+
end
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# Copyright 2020 Google, Inc
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+
# http://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+
require "google/cloud/firestore"
16+
17+
def listen_document project_id:, collection_path: "cities", document_path: "SF"
18+
# project_id = "Your Google Cloud Project ID"
19+
# collection_path = "cities"
20+
# document_path = "SF"
21+
22+
firestore = Google::Cloud::Firestore.new project_id: project_id
23+
# [START fs_listen_document]
24+
doc_ref = firestore.col(collection_path).doc document_path
25+
snapshots = []
26+
27+
# Watch the document.
28+
listener = doc_ref.listen do |snapshot|
29+
puts "Received document snapshot: #{snapshot.document_id}"
30+
snapshots << snapshot
31+
end
32+
# [END fs_listen_document]
33+
34+
# Create the document.
35+
doc_ref.set(
36+
name: "San Francisco",
37+
state: "CA",
38+
country: "USA",
39+
capital: false,
40+
population: 860_000
41+
)
42+
43+
# Wait for the callback.
44+
wait_until { !snapshots.empty? }
45+
46+
# [START fs_detach_listener]
47+
listener.stop
48+
# [END fs_detach_listener]
49+
end
50+
51+
def listen_changes project_id:, collection_path: "cities"
52+
# project_id = "Your Google Cloud Project ID"
53+
# collection_path = "cities"
54+
55+
firestore = Google::Cloud::Firestore.new project_id: project_id
56+
# [START fs_listen_changes]
57+
query = firestore.col(collection_path).where :state, :==, "CA"
58+
added = []
59+
modified = []
60+
removed = []
61+
62+
# Watch the collection query.
63+
listener = query.listen do |snapshot|
64+
puts "Callback received query snapshot."
65+
puts "Current cities in California:"
66+
snapshot.changes.each do |change|
67+
if change.added?
68+
puts "New city: #{change.doc.document_id}"
69+
added << snapshot
70+
elsif change.modified?
71+
puts "Modified city: #{change.doc.document_id}"
72+
modified << snapshot
73+
elsif change.removed?
74+
puts "Removed city: #{change.doc.document_id}"
75+
removed << snapshot
76+
end
77+
end
78+
end
79+
# [END fs_listen_changes]
80+
81+
mtv_doc = firestore.col(collection_path).doc("MTV")
82+
83+
# Create the document.
84+
mtv_doc.set(
85+
name: "Mountain View",
86+
state: "CA",
87+
country: "USA",
88+
capital: false,
89+
population: 80_000
90+
)
91+
92+
wait_until { !added.empty? }
93+
94+
# Update the document.
95+
mtv_doc.update(
96+
name: "Mountain View",
97+
state: "CA",
98+
country: "USA",
99+
capital: false,
100+
population: 90_000
101+
)
102+
103+
wait_until { !modified.empty? }
104+
105+
# Delete the document.
106+
mtv_doc.delete exists: true
107+
108+
wait_until { !removed.empty? }
109+
110+
listener.stop
111+
end
112+
113+
def listen_errors project_id:, collection_path: "cities"
114+
# project_id = "Your Google Cloud Project ID"
115+
# collection_path = "cities"
116+
117+
firestore = Google::Cloud::Firestore.new project_id: project_id
118+
# [START fs_listen_errors]
119+
listener = firestore.col(collection_path).listen do |snapshot|
120+
snapshot.changes.each do |change|
121+
puts "New city: #{change.doc.document_id}" if change.added?
122+
end
123+
end
124+
125+
# Register to be notified when unhandled errors occur.
126+
listener.on_error do |error|
127+
puts "Listen failed: #{error.message}"
128+
end
129+
# [END fs_listen_errors]
130+
131+
listener.stop
132+
end
133+
134+
def listen_multiple project_id:, collection_path: "cities"
135+
# project_id = "Your Google Cloud Project ID"
136+
# collection_path = "cities"
137+
138+
firestore = Google::Cloud::Firestore.new project_id: project_id
139+
# [START fs_listen_multiple]
140+
query = firestore.col(collection_path).where :state, :==, "CA"
141+
docs = []
142+
143+
# Watch the collection query.
144+
listener = query.listen do |snapshot|
145+
puts "Callback received query snapshot."
146+
puts "Current cities in California:"
147+
snapshot.docs.each do |doc|
148+
puts doc.document_id
149+
docs << doc
150+
end
151+
end
152+
# [END fs_listen_multiple]
153+
154+
# Create the document.
155+
firestore.col(collection_path).doc("SF").set(
156+
name: "San Francisco",
157+
state: "CA",
158+
country: "USA",
159+
capital: false,
160+
population: 860_000
161+
)
162+
163+
# Wait for the callback.
164+
wait_until { !docs.empty? }
165+
166+
listener.stop
167+
end
168+
169+
def wait_until &block
170+
wait_count = 0
171+
until block.call
172+
raise "wait_until criteria was not met." if wait_count > 200
173+
wait_count += 1
174+
sleep 0.1
175+
end
176+
end
177+
178+
if $PROGRAM_NAME == __FILE__
179+
project = ENV["FIRESTORE_PROJECT"]
180+
case ARGV.shift
181+
when "listen_document"
182+
listen_document project_id: project
183+
when "listen_changes"
184+
listen_changes project_id: project
185+
when "listen_multiple"
186+
listen_multiple project_id: project
187+
when "listen_errors"
188+
listen_errors project_id: project
189+
else
190+
puts <<~USAGE
191+
Usage: bundle exec ruby query_data.rb [command]
192+
193+
Commands:
194+
listen_document Listen for changes to a document.
195+
listen_changes Listen for changes to a query.
196+
listen_multiple Listen for changes to a query, returning the names of all cities for a state.
197+
listen_errors Handle listening errors.
198+
USAGE
199+
end
200+
end

0 commit comments

Comments
 (0)