google-cloud-datastore 0.20.1 → 0.21.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 +4 -4
- data/lib/google-cloud-datastore.rb +14 -32
- data/lib/google/cloud/datastore.rb +113 -70
- data/lib/google/cloud/datastore/commit.rb +5 -10
- data/lib/google/cloud/datastore/cursor.rb +2 -3
- data/lib/google/cloud/datastore/dataset.rb +17 -22
- data/lib/google/cloud/datastore/dataset/lookup_results.rb +5 -10
- data/lib/google/cloud/datastore/dataset/query_results.rb +24 -36
- data/lib/google/cloud/datastore/entity.rb +26 -39
- data/lib/google/cloud/datastore/key.rb +12 -11
- data/lib/google/cloud/datastore/properties.rb +1 -1
- data/lib/google/cloud/datastore/service.rb +72 -74
- data/lib/google/cloud/datastore/transaction.rb +8 -12
- data/lib/google/cloud/datastore/v1.rb +16 -0
- data/lib/google/cloud/datastore/v1/datastore_api.rb +396 -0
- data/lib/google/cloud/datastore/v1/datastore_client_config.json +58 -0
- data/lib/google/cloud/datastore/version.rb +1 -1
- metadata +37 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd3f4b10ef20aa3a1a65d9f8a20b58ba4a3ffd96
|
4
|
+
data.tar.gz: 554c68061d31f3b04479919f479c9246b784d064
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa1a4af3be5c459603cd02213345995ffc36d518dcc731fd4dcb9d53f9e85c30b9e6bef26f798789a8829ca16952956c3bbddb79a3d3720665fe98e32f554473
|
7
|
+
data.tar.gz: b985b7b68d29f2604c350380cd3e8e4926800aae54b1351e5e5811e7d807d2f67c85ba95da06cb835412a7eb502e22008d7e500699a1f02cc743c02b1651711a
|
@@ -38,9 +38,9 @@ module Google
|
|
38
38
|
# The default scope is:
|
39
39
|
#
|
40
40
|
# * `https://www.googleapis.com/auth/datastore`
|
41
|
-
# @param [Integer] retries Number of times to retry requests on server
|
42
|
-
# error. The default value is `3`. Optional.
|
43
41
|
# @param [Integer] timeout Default timeout to use in requests. Optional.
|
42
|
+
# @param [Hash] client_config A hash of values to override the default
|
43
|
+
# behavior of the API client. See Google::Gax::CallSettings. Optional.
|
44
44
|
#
|
45
45
|
# @return [Google::Cloud::Datastore::Dataset]
|
46
46
|
#
|
@@ -66,10 +66,10 @@ module Google
|
|
66
66
|
# platform_scope = "https://www.googleapis.com/auth/cloud-platform"
|
67
67
|
# datastore = gcloud.datastore scope: platform_scope
|
68
68
|
#
|
69
|
-
def datastore scope: nil,
|
69
|
+
def datastore scope: nil, timeout: nil, client_config: nil
|
70
70
|
Google::Cloud.datastore @project, @keyfile,
|
71
|
-
scope: scope,
|
72
|
-
|
71
|
+
scope: scope, timeout: (timeout || @timeout),
|
72
|
+
client_config: client_config
|
73
73
|
end
|
74
74
|
|
75
75
|
##
|
@@ -91,14 +91,14 @@ module Google
|
|
91
91
|
# The default scope is:
|
92
92
|
#
|
93
93
|
# * `https://www.googleapis.com/auth/datastore`
|
94
|
-
# @param [Integer] retries Number of times to retry requests on server
|
95
|
-
# error. The default value is `3`. Optional.
|
96
94
|
# @param [Integer] timeout Default timeout to use in requests. Optional.
|
95
|
+
# @param [Hash] client_config A hash of values to override the default
|
96
|
+
# behavior of the API client. See Google::Gax::CallSettings. Optional.
|
97
97
|
#
|
98
98
|
# @return [Google::Cloud::Datastore::Dataset]
|
99
99
|
#
|
100
100
|
# @example
|
101
|
-
# require "google/cloud
|
101
|
+
# require "google/cloud"
|
102
102
|
#
|
103
103
|
# datastore = Google::Cloud.datastore "my-todo-project",
|
104
104
|
# "/path/to/keyfile.json"
|
@@ -108,34 +108,16 @@ module Google
|
|
108
108
|
# t["done"] = false
|
109
109
|
# t["priority"] = 4
|
110
110
|
# t["description"] = "Learn Cloud Datastore"
|
111
|
-
# end
|
111
|
+
# end ``
|
112
112
|
#
|
113
113
|
# datastore.save task
|
114
114
|
#
|
115
|
-
def self.datastore project = nil, keyfile = nil, scope: nil,
|
116
|
-
|
115
|
+
def self.datastore project = nil, keyfile = nil, scope: nil, timeout: nil,
|
116
|
+
client_config: nil
|
117
117
|
require "google/cloud/datastore"
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
if ENV["DATASTORE_EMULATOR_HOST"]
|
123
|
-
return Google::Cloud::Datastore::Dataset.new(
|
124
|
-
Google::Cloud::Datastore::Service.new(
|
125
|
-
project, :this_channel_is_insecure,
|
126
|
-
host: ENV["DATASTORE_EMULATOR_HOST"], retries: retries))
|
127
|
-
end
|
128
|
-
|
129
|
-
if keyfile.nil?
|
130
|
-
credentials = Google::Cloud::Datastore::Credentials.default scope: scope
|
131
|
-
else
|
132
|
-
credentials = Google::Cloud::Datastore::Credentials.new(
|
133
|
-
keyfile, scope: scope)
|
134
|
-
end
|
135
|
-
|
136
|
-
Google::Cloud::Datastore::Dataset.new(
|
137
|
-
Google::Cloud::Datastore::Service.new(
|
138
|
-
project, credentials, retries: retries, timeout: timeout))
|
118
|
+
Google::Cloud::Datastore.new project: project, keyfile: keyfile,
|
119
|
+
scope: scope, timeout: timeout,
|
120
|
+
client_config: client_config
|
139
121
|
end
|
140
122
|
end
|
141
123
|
end
|
@@ -36,11 +36,12 @@ module Google
|
|
36
36
|
# is taken care of for you.
|
37
37
|
#
|
38
38
|
# ```ruby
|
39
|
-
# require "google/cloud"
|
39
|
+
# require "google/cloud/datastore"
|
40
40
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
41
|
+
# datastore = Google::Cloud::Datastore.new(
|
42
|
+
# project: "my-todo-project",
|
43
|
+
# keyfile: "/path/to/keyfile.json"
|
44
|
+
# )
|
44
45
|
#
|
45
46
|
# task = datastore.find "Task", "sampleTask"
|
46
47
|
# task["priority"] = 5
|
@@ -65,10 +66,9 @@ module Google
|
|
65
66
|
# {Google::Cloud::Datastore::Dataset#find} and passing the parts of the key:
|
66
67
|
#
|
67
68
|
# ```ruby
|
68
|
-
# require "google/cloud"
|
69
|
+
# require "google/cloud/datastore"
|
69
70
|
#
|
70
|
-
#
|
71
|
-
# datastore = gcloud.datastore
|
71
|
+
# datastore = Google::Cloud::Datastore.new
|
72
72
|
#
|
73
73
|
# task = datastore.find "Task", "sampleTask"
|
74
74
|
# ```
|
@@ -77,10 +77,9 @@ module Google
|
|
77
77
|
# object:
|
78
78
|
#
|
79
79
|
# ```ruby
|
80
|
-
# require "google/cloud"
|
80
|
+
# require "google/cloud/datastore"
|
81
81
|
#
|
82
|
-
#
|
83
|
-
# datastore = gcloud.datastore
|
82
|
+
# datastore = Google::Cloud::Datastore.new
|
84
83
|
#
|
85
84
|
# task_key = datastore.key "Task", 123456
|
86
85
|
# task = datastore.find task_key
|
@@ -94,10 +93,9 @@ module Google
|
|
94
93
|
# (See {Google::Cloud::Datastore::Query#where})
|
95
94
|
#
|
96
95
|
# ```ruby
|
97
|
-
# require "google/cloud"
|
96
|
+
# require "google/cloud/datastore"
|
98
97
|
#
|
99
|
-
#
|
100
|
-
# datastore = gcloud.datastore
|
98
|
+
# datastore = Google::Cloud::Datastore.new
|
101
99
|
#
|
102
100
|
# query = datastore.query("Task").
|
103
101
|
# where("done", "=", false)
|
@@ -108,10 +106,9 @@ module Google
|
|
108
106
|
# Records can also be ordered. (See {Google::Cloud::Datastore::Query#order})
|
109
107
|
#
|
110
108
|
# ```ruby
|
111
|
-
# require "google/cloud"
|
109
|
+
# require "google/cloud/datastore"
|
112
110
|
#
|
113
|
-
#
|
114
|
-
# datastore = gcloud.datastore
|
111
|
+
# datastore = Google::Cloud::Datastore.new
|
115
112
|
#
|
116
113
|
# query = datastore.query("Task").
|
117
114
|
# order("created")
|
@@ -123,10 +120,9 @@ module Google
|
|
123
120
|
# (See {Google::Cloud::Datastore::Query#limit})
|
124
121
|
#
|
125
122
|
# ```ruby
|
126
|
-
# require "google/cloud"
|
123
|
+
# require "google/cloud/datastore"
|
127
124
|
#
|
128
|
-
#
|
129
|
-
# datastore = gcloud.datastore
|
125
|
+
# datastore = Google::Cloud::Datastore.new
|
130
126
|
#
|
131
127
|
# query = datastore.query("Task").
|
132
128
|
# limit(5)
|
@@ -138,10 +134,9 @@ module Google
|
|
138
134
|
# (See {Google::Cloud::Datastore::Query#ancestor})
|
139
135
|
#
|
140
136
|
# ```ruby
|
141
|
-
# require "google/cloud"
|
137
|
+
# require "google/cloud/datastore"
|
142
138
|
#
|
143
|
-
#
|
144
|
-
# datastore = gcloud.datastore
|
139
|
+
# datastore = Google::Cloud::Datastore.new
|
145
140
|
#
|
146
141
|
# task_list_key = datastore.key "TaskList", "default"
|
147
142
|
#
|
@@ -160,10 +155,9 @@ module Google
|
|
160
155
|
# Datastore to return them all.
|
161
156
|
#
|
162
157
|
# ```ruby
|
163
|
-
# require "google/cloud"
|
158
|
+
# require "google/cloud/datastore"
|
164
159
|
#
|
165
|
-
#
|
166
|
-
# datastore = gcloud.datastore
|
160
|
+
# datastore = Google::Cloud::Datastore.new
|
167
161
|
#
|
168
162
|
# query = datastore.query("Task")
|
169
163
|
# tasks = datastore.run query
|
@@ -182,10 +176,9 @@ module Google
|
|
182
176
|
# saved. If the key is incomplete then it will be completed when saved.
|
183
177
|
#
|
184
178
|
# ```ruby
|
185
|
-
# require "google/cloud"
|
179
|
+
# require "google/cloud/datastore"
|
186
180
|
#
|
187
|
-
#
|
188
|
-
# datastore = gcloud.datastore
|
181
|
+
# datastore = Google::Cloud::Datastore.new
|
189
182
|
#
|
190
183
|
# task = datastore.entity "Task" do |t|
|
191
184
|
# t["type"] = "Personal"
|
@@ -201,10 +194,9 @@ module Google
|
|
201
194
|
# Multiple new entities may be created in a batch.
|
202
195
|
#
|
203
196
|
# ```ruby
|
204
|
-
# require "google/cloud"
|
197
|
+
# require "google/cloud/datastore"
|
205
198
|
#
|
206
|
-
#
|
207
|
-
# datastore = gcloud.datastore
|
199
|
+
# datastore = Google::Cloud::Datastore.new
|
208
200
|
#
|
209
201
|
# task1 = datastore.entity "Task" do |t|
|
210
202
|
# t["type"] = "Personal"
|
@@ -251,10 +243,9 @@ module Google
|
|
251
243
|
# {Google::Cloud::Datastore::Dataset#save}.
|
252
244
|
#
|
253
245
|
# ```ruby
|
254
|
-
# require "google/cloud"
|
246
|
+
# require "google/cloud/datastore"
|
255
247
|
#
|
256
|
-
#
|
257
|
-
# datastore = gcloud.datastore
|
248
|
+
# datastore = Google::Cloud::Datastore.new
|
258
249
|
#
|
259
250
|
# task = datastore.find "Task", "sampleTask"
|
260
251
|
# # Read the priority property
|
@@ -268,10 +259,9 @@ module Google
|
|
268
259
|
# Array properties can be used to store more than one value.
|
269
260
|
#
|
270
261
|
# ```ruby
|
271
|
-
# require "google/cloud"
|
262
|
+
# require "google/cloud/datastore"
|
272
263
|
#
|
273
|
-
#
|
274
|
-
# datastore = gcloud.datastore
|
264
|
+
# datastore = Google::Cloud::Datastore.new
|
275
265
|
#
|
276
266
|
# task = datastore.entity "Task", "sampleTask" do |t|
|
277
267
|
# t["tags"] = ["fun", "programming"]
|
@@ -286,10 +276,9 @@ module Google
|
|
286
276
|
# or the entity's key object.
|
287
277
|
#
|
288
278
|
# ```ruby
|
289
|
-
# require "google/cloud"
|
279
|
+
# require "google/cloud/datastore"
|
290
280
|
#
|
291
|
-
#
|
292
|
-
# datastore = gcloud.datastore
|
281
|
+
# datastore = Google::Cloud::Datastore.new
|
293
282
|
#
|
294
283
|
# task = datastore.find "Task", "sampleTask"
|
295
284
|
# datastore.delete task
|
@@ -298,10 +287,9 @@ module Google
|
|
298
287
|
# Multiple entities may be deleted in a batch.
|
299
288
|
#
|
300
289
|
# ```ruby
|
301
|
-
# require "google/cloud"
|
290
|
+
# require "google/cloud/datastore"
|
302
291
|
#
|
303
|
-
#
|
304
|
-
# datastore = gcloud.datastore
|
292
|
+
# datastore = Google::Cloud::Datastore.new
|
305
293
|
#
|
306
294
|
# task_key1 = datastore.key "Task", "sampleTask1"
|
307
295
|
# task_key2 = datastore.key "Task", "sampleTask2"
|
@@ -316,10 +304,9 @@ module Google
|
|
316
304
|
# block completes.
|
317
305
|
#
|
318
306
|
# ```ruby
|
319
|
-
# require "google/cloud"
|
307
|
+
# require "google/cloud/datastore"
|
320
308
|
#
|
321
|
-
#
|
322
|
-
# datastore = gcloud.datastore
|
309
|
+
# datastore = Google::Cloud::Datastore.new
|
323
310
|
#
|
324
311
|
# task_key = datastore.key "Task", "sampleTask"
|
325
312
|
#
|
@@ -340,10 +327,9 @@ module Google
|
|
340
327
|
# allowing you to commit or rollback manually.
|
341
328
|
#
|
342
329
|
# ```ruby
|
343
|
-
# require "google/cloud"
|
330
|
+
# require "google/cloud/datastore"
|
344
331
|
#
|
345
|
-
#
|
346
|
-
# datastore = gcloud.datastore
|
332
|
+
# datastore = Google::Cloud::Datastore.new
|
347
333
|
#
|
348
334
|
# task_key = datastore.key "Task", "sampleTask"
|
349
335
|
#
|
@@ -458,30 +444,16 @@ module Google
|
|
458
444
|
# end
|
459
445
|
# ```
|
460
446
|
#
|
461
|
-
# ## Configuring
|
447
|
+
# ## Configuring timeout
|
462
448
|
#
|
463
|
-
# You can configure
|
464
|
-
# retried. When an API request fails, the response will be inspected to see
|
465
|
-
# if the request meets criteria indicating that it may succeed on retry,
|
466
|
-
# such as `500` and `503` status codes or a specific internal error code
|
467
|
-
# such as `rateLimitExceeded`. If it meets the criteria, the request will be
|
468
|
-
# retried after a delay. If another error occurs, the delay will be
|
469
|
-
# increased before a subsequent attempt, until the `retries` limit is
|
470
|
-
# reached.
|
471
|
-
#
|
472
|
-
# You can also set the request `timeout` value in seconds.
|
449
|
+
# You can configure the request `timeout` value in seconds.
|
473
450
|
#
|
474
451
|
# ```ruby
|
475
|
-
# require "google/cloud"
|
452
|
+
# require "google/cloud/datastore"
|
476
453
|
#
|
477
|
-
#
|
478
|
-
# datastore = gcloud.datastore retries: 10, timeout: 120
|
454
|
+
# datastore = Google::Cloud::Datastore.new timeout: 120
|
479
455
|
# ```
|
480
456
|
#
|
481
|
-
# See the [Datastore error
|
482
|
-
# codes](https://cloud.google.com/datastore/docs/concepts/errors#error_codes)
|
483
|
-
# for a list of error conditions.
|
484
|
-
#
|
485
457
|
# ## The Cloud Datastore Emulator
|
486
458
|
#
|
487
459
|
# As of this release, the Cloud Datastore emulator that is part of the
|
@@ -508,13 +480,12 @@ module Google
|
|
508
480
|
# environment variable:
|
509
481
|
#
|
510
482
|
# ```ruby
|
511
|
-
# require "google/cloud"
|
483
|
+
# require "google/cloud/datastore"
|
512
484
|
#
|
513
485
|
# # Make Datastore use the emulator
|
514
486
|
# ENV["DATASTORE_EMULATOR_HOST"] = "localhost:8978"
|
515
487
|
#
|
516
|
-
#
|
517
|
-
# datastore = gcloud.datastore
|
488
|
+
# datastore = Google::Cloud::Datastore.new project: "emulator-project-id"
|
518
489
|
#
|
519
490
|
# task = datastore.entity "Task", "emulatorTask" do |t|
|
520
491
|
# t["type"] = "Testing"
|
@@ -527,6 +498,78 @@ module Google
|
|
527
498
|
# ```
|
528
499
|
#
|
529
500
|
module Datastore
|
501
|
+
##
|
502
|
+
# Creates a new object for connecting to the Datastore service.
|
503
|
+
# Each call creates a new connection.
|
504
|
+
#
|
505
|
+
# For more information on connecting to Google Cloud see the
|
506
|
+
# [Authentication
|
507
|
+
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
|
508
|
+
#
|
509
|
+
# @param [String] project Dataset identifier for the Datastore you are
|
510
|
+
# connecting to.
|
511
|
+
# @param [String, Hash] keyfile Keyfile downloaded from Google Cloud. If
|
512
|
+
# file path the file must be readable.
|
513
|
+
# @param [String, Array<String>] scope The OAuth 2.0 scopes controlling
|
514
|
+
# the set of resources and operations that the connection can access.
|
515
|
+
# See [Using OAuth 2.0 to Access Google
|
516
|
+
# APIs](https://developers.google.com/identity/protocols/OAuth2).
|
517
|
+
#
|
518
|
+
# The default scope is:
|
519
|
+
#
|
520
|
+
# * `https://www.googleapis.com/auth/datastore`
|
521
|
+
# @param [Integer] timeout Default timeout to use in requests. Optional.
|
522
|
+
# @param [Hash] client_config A hash of values to override the default
|
523
|
+
# behavior of the API client. See Google::Gax::CallSettings. Optional.
|
524
|
+
#
|
525
|
+
# @return [Google::Cloud::Datastore::Dataset]
|
526
|
+
#
|
527
|
+
# @example
|
528
|
+
# require "google/cloud/datastore"
|
529
|
+
#
|
530
|
+
# datastore = Google::Cloud::Datastore.new(
|
531
|
+
# project: "my-todo-project",
|
532
|
+
# keyfile: "/path/to/keyfile.json"
|
533
|
+
# )
|
534
|
+
#
|
535
|
+
# task = datastore.entity "Task", "sampleTask" do |t|
|
536
|
+
# t["type"] = "Personal"
|
537
|
+
# t["done"] = false
|
538
|
+
# t["priority"] = 4
|
539
|
+
# t["description"] = "Learn Cloud Datastore"
|
540
|
+
# end
|
541
|
+
#
|
542
|
+
# datastore.save task
|
543
|
+
#
|
544
|
+
def self.new project: nil, keyfile: nil, scope: nil, timeout: nil,
|
545
|
+
client_config: nil
|
546
|
+
project ||= Google::Cloud::Datastore::Dataset.default_project
|
547
|
+
project = project.to_s # Always cast to a string
|
548
|
+
fail ArgumentError, "project is missing" if project.empty?
|
549
|
+
|
550
|
+
if ENV["DATASTORE_EMULATOR_HOST"]
|
551
|
+
return Google::Cloud::Datastore::Dataset.new(
|
552
|
+
Google::Cloud::Datastore::Service.new(
|
553
|
+
project, :this_channel_is_insecure,
|
554
|
+
host: ENV["DATASTORE_EMULATOR_HOST"],
|
555
|
+
client_config: client_config))
|
556
|
+
end
|
557
|
+
credentials = credentials_with_scope keyfile, scope
|
558
|
+
Google::Cloud::Datastore::Dataset.new(
|
559
|
+
Google::Cloud::Datastore::Service.new(
|
560
|
+
project, credentials, timeout: timeout,
|
561
|
+
client_config: client_config))
|
562
|
+
end
|
563
|
+
|
564
|
+
##
|
565
|
+
# @private
|
566
|
+
def self.credentials_with_scope keyfile, scope
|
567
|
+
if keyfile.nil?
|
568
|
+
Google::Cloud::Datastore::Credentials.default(scope: scope)
|
569
|
+
else
|
570
|
+
Google::Cloud::Datastore::Credentials.new(keyfile, scope: scope)
|
571
|
+
end
|
572
|
+
end
|
530
573
|
end
|
531
574
|
end
|
532
575
|
end
|
@@ -23,8 +23,7 @@ module Google
|
|
23
23
|
# made in a single commit.
|
24
24
|
#
|
25
25
|
# @example
|
26
|
-
#
|
27
|
-
# datastore = gcloud.datastore
|
26
|
+
# datastore = Google::Cloud::Datastore.new
|
28
27
|
# datastore.commit do |c|
|
29
28
|
# c.save task1, task2
|
30
29
|
# c.delete entity1, entity2
|
@@ -48,8 +47,7 @@ module Google
|
|
48
47
|
# @param [Entity] entities One or more Entity objects to save.
|
49
48
|
#
|
50
49
|
# @example
|
51
|
-
#
|
52
|
-
# datastore = gcloud.datastore
|
50
|
+
# datastore = Google::Cloud::Datastore.new
|
53
51
|
# datastore.commit do |c|
|
54
52
|
# c.save task1, task2
|
55
53
|
# end
|
@@ -68,8 +66,7 @@ module Google
|
|
68
66
|
# @param [Entity] entities One or more Entity objects to insert.
|
69
67
|
#
|
70
68
|
# @example
|
71
|
-
#
|
72
|
-
# datastore = gcloud.datastore
|
69
|
+
# datastore = Google::Cloud::Datastore.new
|
73
70
|
# datastore.commit do |c|
|
74
71
|
# c.insert task1, task2
|
75
72
|
# end
|
@@ -87,8 +84,7 @@ module Google
|
|
87
84
|
# @param [Entity] entities One or more Entity objects to update.
|
88
85
|
#
|
89
86
|
# @example
|
90
|
-
#
|
91
|
-
# datastore = gcloud.datastore
|
87
|
+
# datastore = Google::Cloud::Datastore.new
|
92
88
|
# datastore.commit do |c|
|
93
89
|
# c.update task1, task2
|
94
90
|
# end
|
@@ -107,8 +103,7 @@ module Google
|
|
107
103
|
# objects to remove.
|
108
104
|
#
|
109
105
|
# @example
|
110
|
-
#
|
111
|
-
# datastore = gcloud.datastore
|
106
|
+
# datastore = Google::Cloud::Datastore.new
|
112
107
|
# datastore.commit do |c|
|
113
108
|
# c.delete task1, task2
|
114
109
|
# end
|