arangorb 1.0.0 → 1.1.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.
data/lib/ArangoRB_DB.rb CHANGED
@@ -12,6 +12,18 @@ class ArangoDatabase < ArangoServer
12
12
  end
13
13
 
14
14
  attr_reader :database # TESTED
15
+ alias name database
16
+
17
+ # === RETRIEVE ===
18
+
19
+ def [](collection_name)
20
+ ArangoCollection.new(collection: collection_name, database: @database)
21
+ end
22
+ alias collection []
23
+
24
+ def graph(graph_name)
25
+ ArangoGraph.new(graph: graph_name, database: @database)
26
+ end
15
27
 
16
28
  # === GET ===
17
29
 
@@ -58,38 +70,16 @@ class ArangoDatabase < ArangoServer
58
70
  query = { "excludeSystem": excludeSystem }.delete_if{|k,v| v.nil?}
59
71
  request = @@request.merge({ :query => query })
60
72
  result = self.class.get("/_db/#{@database}/_api/collection", request)
61
- if @@async == "store"
62
- result.headers["x-arango-async-id"]
63
- else
64
- result = result.parsed_response
65
- if @@verbose
66
- result
67
- else
68
- if result["error"]
69
- result["errorMessage"]
70
- else
71
- result["result"].map{|x| ArangoCollection.new(database: @database, collection: x["name"])}
72
- end
73
- end
74
- end
73
+ return result.headers["x-arango-async-id"] if @@async == "store"
74
+ result = result.parsed_response
75
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| ArangoCollection.new(database: @database, collection: x["name"])}
75
76
  end
76
77
 
77
78
  def graphs # TESTED
78
79
  result = self.class.get("/_db/#{@database}/_api/gharial", @@request)
79
- if @@async == "store"
80
- result.headers["x-arango-async-id"]
81
- else
82
- result = result.parsed_response
83
- if @@verbose
84
- result
85
- else
86
- if result["error"]
87
- result["errorMessage"]
88
- else
89
- result["graphs"].map{|x| ArangoGraph.new(database: @database, graph: x["_key"], edgeDefinitions: x["edgeDefinitions"], orphanCollections: x["orphanCollections"])}
90
- end
91
- end
92
- end
80
+ return result.headers["x-arango-async-id"] if @@async == "store"
81
+ result = result.parsed_response
82
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["graphs"].map{|x| ArangoGraph.new(database: @database, graph: x["_key"], edgeDefinitions: x["edgeDefinitions"], orphanCollections: x["orphanCollections"])}
93
83
  end
94
84
 
95
85
  def functions # TESTED
@@ -175,49 +165,6 @@ class ArangoDatabase < ArangoServer
175
165
  self.class.return_result result: result, caseTrue: true
176
166
  end
177
167
 
178
- # # === ASYNC ===
179
- #
180
- # def pendingAsync # TESTED
181
- # result = self.class.get("/_db/#{@database}/_api/job/pending")
182
- # return_result_async result: result
183
- # end
184
- #
185
- # def fetchAsync(id:) # TESTED
186
- # result = self.class.put("/_db/#{@database}/_api/job/#{id}")
187
- # return_result_async result: result
188
- # end
189
- #
190
- # def retrieveAsync(type:) # TESTED
191
- # result = self.class.get("/_db/#{@database}/_api/job/#{type}")
192
- # return_result_async result: result
193
- # end
194
- #
195
- # def retrieveDoneAsync # TESTED
196
- # retrieveAsync(type: "done")
197
- # end
198
- #
199
- # def retrievePendingAsync # TESTED
200
- # retrieveAsync(type: "pending")
201
- # end
202
- #
203
- # def cancelAsync(id:) # TESTED
204
- # result = self.class.put("/_db/#{@database}/_api/job/#{id}/cancel")
205
- # return_result_async result: result
206
- # end
207
- #
208
- # def destroyAsync(type:) # TESTED
209
- # result = self.class.delete("/_db/#{@database}/_api/job/#{type}")
210
- # return_result_async result: result, caseTrue: true
211
- # end
212
- #
213
- # def destroyAllAsync # TESTED
214
- # destroyAsync(type: "all")
215
- # end
216
- #
217
- # def destroyExpiredAsync # TESTED
218
- # destroyAsync(type: "expired")
219
- # end
220
-
221
168
  # === REPLICATION ===
222
169
 
223
170
  def inventory(includeSystem: false) # TESTED
@@ -374,23 +321,4 @@ class ArangoDatabase < ArangoServer
374
321
  result = self.class.put("/_api/user/#{user}/database/#{@database}", request)
375
322
  self.class.return_result result: result, caseTrue: true
376
323
  end
377
-
378
- # # === UTILITY ===
379
- #
380
- # def return_result_async(result:, caseTrue: false)
381
- # result = result.parsed_response
382
- # if @@verbose || !result.is_a?(Hash)
383
- # result
384
- # else
385
- # if result["error"]
386
- # result["errorMessage"]
387
- # else
388
- # if caseTrue
389
- # true
390
- # else
391
- # result.delete_if{|k,v| k == "error" || k == "code"}
392
- # end
393
- # end
394
- # end
395
- # end
396
324
  end
data/lib/ArangoRB_Doc.rb CHANGED
@@ -24,6 +24,9 @@ class ArangoDocument < ArangoServer
24
24
  body["_key"] = @key
25
25
  @id = "#{@collection}/#{@key}"
26
26
  end
27
+ elsif key.is_a?(ArangoDocument)
28
+ @key = key.key
29
+ @id = key.id
27
30
  else
28
31
  raise "key should be a String, not a #{key.class}"
29
32
  end
@@ -53,7 +56,18 @@ class ArangoDocument < ArangoServer
53
56
  end
54
57
  end
55
58
 
56
- attr_reader :key, :id, :body, :collection, :database
59
+ attr_reader :key, :id, :body
60
+ alias name key
61
+
62
+ # === RETRIEVE ===
63
+
64
+ def collection
65
+ ArangoCollection.new(collection: @collection, database: @database)
66
+ end
67
+
68
+ def database
69
+ ArangoDatabase.new(database: @database)
70
+ end
57
71
 
58
72
  # === GET ===
59
73
 
@@ -69,21 +83,19 @@ class ArangoDocument < ArangoServer
69
83
  result = self.class.get("/_db/#{@database}/_api/edges/#{collection}", request)
70
84
  return result.headers["x-arango-async-id"] if @@async == "store"
71
85
  result = result.parsed_response
72
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["edges"].map{|edge|
73
- ArangoDocument.new(key: edge["_key"], collection: collection, database: @database, body: edge)
74
- }
86
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["edges"].map{|edge| ArangoDocument.new(key: edge["_key"], collection: collection, database: @database, body: edge)}
75
87
  end
76
88
 
77
- def in(collection) # TESTED
78
- self.retrieve_edges collection: collection, direction: "in"
89
+ def in(edgeCollection) # TESTED
90
+ self.retrieve_edges collection: edgeCollection, direction: "in"
79
91
  end
80
92
 
81
- def out(collection) # TESTED
82
- self.retrieve_edges collection: collection, direction: "out"
93
+ def out(edgeCollection) # TESTED
94
+ self.retrieve_edges collection: edgeCollection, direction: "out"
83
95
  end
84
96
 
85
- def any(collection) # TESTED
86
- self.retrieve_edges collection: collection
97
+ def any(edgeCollection) # TESTED
98
+ self.retrieve_edges collection: edgeCollection
87
99
  end
88
100
 
89
101
  def from # TESTED
@@ -222,14 +234,11 @@ class ArangoDocument < ArangoServer
222
234
  end
223
235
  result
224
236
  else
225
- if result["error"]
226
- result["errorMessage"]
227
- else
228
- @key = result["_key"]
229
- @id = "#{@collection}/#{@key}"
230
- @body = @body.merge(body)
231
- self
232
- end
237
+ return result["errorMessage"] if result["error"]
238
+ @key = result["_key"]
239
+ @id = "#{@collection}/#{@key}"
240
+ @body = @body.merge(body)
241
+ return self
233
242
  end
234
243
  else
235
244
  result = self.class.patch("/_db/#{@database}/_api/document/#{@collection}", request)
@@ -262,34 +271,26 @@ class ArangoDocument < ArangoServer
262
271
  # === UTILITY ===
263
272
 
264
273
  def return_result(result:, body: {}, caseTrue: false, key: nil)
265
- if @@async == "store"
266
- result.headers["x-arango-async-id"]
267
- else
268
- result = result.parsed_response
269
- if @@verbose || !result.is_a?(Hash)
270
- resultTemp = result
271
- unless result["errorMessage"]
272
- result.delete("error")
273
- result.delete("code")
274
- @key = result["_key"]
275
- @collection = result["_id"].split("/")[0]
276
- @body = result.merge(body)
277
- end
278
- resultTemp
279
- else
280
- if result["error"]
281
- result["errorMessage"]
282
- else
283
- return true if caseTrue
284
- result.delete("error")
285
- result.delete("code")
286
- @key = result["_key"]
287
- @collection = result["_id"].split("/")[0]
288
- @id = "#{@collection}/#{@key}"
289
- @body = result.merge(body)
290
- key.nil? ? self : result[key]
291
- end
274
+ return result.headers["x-arango-async-id"] if @@async == "store"
275
+ result = result.parsed_response
276
+ if @@verbose || !result.is_a?(Hash)
277
+ resultTemp = result
278
+ unless result["errorMessage"]
279
+ result.delete_if{|k,v| k == "error" || k == "code"}
280
+ @key = result["_key"]
281
+ @collection = result["_id"].split("/")[0]
282
+ @body = result.merge(body)
292
283
  end
284
+ return resultTemp
285
+ else
286
+ return result["errorMessage"] if result["error"]
287
+ return true if caseTrue
288
+ result.delete_if{|k,v| k == "error" || k == "code"}
289
+ @key = result["_key"]
290
+ @collection = result["_id"].split("/")[0]
291
+ @id = "#{@collection}/#{@key}"
292
+ @body = result.merge(body)
293
+ key.nil? ? self : result[key]
293
294
  end
294
295
  end
295
296
  end
data/lib/ArangoRB_Edg.rb CHANGED
@@ -32,6 +32,9 @@ class ArangoEdge < ArangoDocument
32
32
  body["_key"] = @key
33
33
  @id = "#{@collection}/#{@key}"
34
34
  end
35
+ elsif key.is_a?(ArangoDocument)
36
+ @key = key.key
37
+ @id = key.id
35
38
  else
36
39
  raise "key should be a String, not a #{key.class}"
37
40
  end
@@ -61,27 +64,27 @@ class ArangoEdge < ArangoDocument
61
64
  end
62
65
  end
63
66
 
64
- attr_reader :key, :id, :body, :database, :graph, :collection
67
+ attr_reader :key, :id, :body
68
+
69
+ # === RETRIEVE ===
70
+
71
+ def graph
72
+ ArangoGraph.new(graph: @graph, database: @database)
73
+ end
65
74
 
66
75
  # === GET ===
67
76
 
68
77
  def retrieve # TESTED
69
78
  result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@id}", @@request)
70
- if @@async == "store"
71
- result.headers["x-arango-async-id"]
79
+ return result.headers["x-arango-async-id"] if @@async == "store"
80
+ result = result.parsed_response
81
+ if @@verbose
82
+ @body = result["edge"] unless result["error"]
83
+ result
72
84
  else
73
- result = result.parsed_response
74
- if @@verbose
75
- @body = result["edge"] unless result["error"]
76
- result
77
- else
78
- if result["error"]
79
- result["errorMessage"]
80
- else
81
- @body = result["edge"]
82
- self
83
- end
84
- end
85
+ return result["errorMessage"] if result["error"]
86
+ @body = result["edge"]
87
+ self
85
88
  end
86
89
  end
87
90
 
@@ -112,28 +115,22 @@ class ArangoEdge < ArangoDocument
112
115
  query = {"waitForSync" => waitForSync, "keepNull" => keepNull}.delete_if{|k,v| v.nil?}
113
116
  request = @@request.merge({ :body => body.to_json, :query => query })
114
117
  result = self.class.patch("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@id}", request)
115
- if @@async == "store"
116
- result.headers["x-arango-async-id"]
117
- else
118
- result = result.parsed_response
119
- if @@verbose
120
- unless result["error"]
121
- @key = result["_key"]
122
- @id = "#{@collection}/#{@key}"
123
- @body = body
124
- end
125
- result
126
- else
127
- if result["error"]
128
- result["errorMessage"]
129
- else
130
- @key = result["edge"]["_key"]
131
- @id = "#{@collection}/#{@key}"
132
- @body = @body.merge(body)
133
- @body = @body.merge(result["edge"])
134
- self
135
- end
118
+ return result.headers["x-arango-async-id"] if @@async == "store"
119
+ result = result.parsed_response
120
+ if @@verbose
121
+ unless result["error"]
122
+ @key = result["_key"]
123
+ @id = "#{@collection}/#{@key}"
124
+ @body = body
136
125
  end
126
+ result
127
+ else
128
+ return result["errorMessage"] if result["error"]
129
+ @key = result["edge"]["_key"]
130
+ @id = "#{@collection}/#{@key}"
131
+ @body = @body.merge(body)
132
+ @body = @body.merge(result["edge"])
133
+ self
137
134
  end
138
135
  end
139
136
 
@@ -149,28 +146,22 @@ class ArangoEdge < ArangoDocument
149
146
  # === UTILITY ===
150
147
 
151
148
  def return_result(result:, body: {}, caseTrue: false)
152
- if @@async == "store"
153
- result.headers["x-arango-async-id"]
154
- else
155
- result = result.parsed_response
156
- if @@verbose
157
- unless result["error"]
158
- @key = result["edge"]["_key"]
159
- @id = "#{@collection}/#{@key}"
160
- @body = body
161
- end
162
- result
163
- else
164
- if result["error"]
165
- result["errorMessage"]
166
- else
167
- return true if caseTrue
168
- @key = result["edge"]["_key"]
169
- @id = "#{@collection}/#{@key}"
170
- @body = body
171
- self
172
- end
149
+ return result.headers["x-arango-async-id"] if @@async == "store"
150
+ result = result.parsed_response
151
+ if @@verbose
152
+ unless result["error"]
153
+ @key = result["edge"]["_key"]
154
+ @id = "#{@collection}/#{@key}"
155
+ @body = body
173
156
  end
157
+ result
158
+ else
159
+ return result["errorMessage"] if result["error"]
160
+ return true if caseTrue
161
+ @key = result["edge"]["_key"]
162
+ @id = "#{@collection}/#{@key}"
163
+ @body = body
164
+ self
174
165
  end
175
166
  end
176
167
  end
data/lib/ArangoRB_Gra.rb CHANGED
@@ -32,27 +32,25 @@ class ArangoGraph < ArangoServer
32
32
  end
33
33
 
34
34
  attr_reader :graph, :edgeDefinitions, :orphanCollections, :database
35
+ alias name graph
36
+
37
+ # === RETRIEVE ===
38
+
39
+ def database
40
+ ArangoDatabase.new(database: @database)
41
+ end
35
42
 
36
43
  # === GET ===
37
44
 
38
45
  def retrieve # TESTED
39
46
  result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}", @@request)
40
- if @@async == "store"
41
- result.headers["x-arango-async-id"]
42
- else
43
- result = result.parsed_response
44
- if @@verbose
45
- result
46
- else
47
- if result["error"]
48
- result["errorMessage"]
49
- else
50
- @edgeDefinitions = result["graph"]["edgeDefinitions"]
51
- @orphanCollections = result["graph"]["orphanCollections"]
52
- self
53
- end
54
- end
55
- end
47
+ return result.headers["x-arango-async-id"] if @@async == "store"
48
+ result = result.parsed_response
49
+ return result if @@verbose
50
+ return result["errorMessage"] if result["error"]
51
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
52
+ @orphanCollections = result["graph"]["orphanCollections"]
53
+ self
56
54
  end
57
55
 
58
56
  # === POST ===
@@ -61,36 +59,27 @@ class ArangoGraph < ArangoServer
61
59
  body = { "name" => @graph, "edgeDefinitions" => @edgeDefinitions, "orphanCollections" => @orphanCollections }
62
60
  request = @@request.merge({ :body => body.to_json })
63
61
  result = self.class.post("/_db/#{@database}/_api/gharial", request)
64
- if @@async == "store"
65
- result.headers["x-arango-async-id"]
66
- else
67
- result = result.parsed_response
68
- @@verbose ? result : result["error"] ? result["errorMessage"] : self
69
- end
62
+ return result.headers["x-arango-async-id"] if @@async == "store"
63
+ result = result.parsed_response
64
+ @@verbose ? result : result["error"] ? result["errorMessage"] : self
70
65
  end
71
66
 
72
67
  # === DELETE ===
73
68
 
74
69
  def destroy # TESTED
75
70
  result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}", @@request)
76
- if @@async == "store"
77
- result.headers["x-arango-async-id"]
78
- else
79
- result = result.parsed_response
80
- @@verbose ? result : result["error"] ? result["errorMessage"] : true
81
- end
71
+ return result.headers["x-arango-async-id"] if @@async == "store"
72
+ result = result.parsed_response
73
+ @@verbose ? result : result["error"] ? result["errorMessage"] : true
82
74
  end
83
75
 
84
76
  # === VERTEX COLLECTION ===
85
77
 
86
78
  def vertexCollections # TESTED
87
79
  result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}/vertex", @@request)
88
- if @@async == "store"
89
- result.headers["x-arango-async-id"]
90
- else
91
- result = result.parsed_response
92
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["collections"].map{|x| ArangoCollection.new(collection: x)}
93
- end
80
+ return result.headers["x-arango-async-id"] if @@async == "store"
81
+ result = result.parsed_response
82
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["collections"].map{|x| ArangoCollection.new(collection: x)}
94
83
  end
95
84
 
96
85
  def addVertexCollection(collection:) # TESTED
@@ -98,40 +87,30 @@ class ArangoGraph < ArangoServer
98
87
  body = { "collection" => collection }.to_json
99
88
  request = @@request.merge({ :body => body })
100
89
  result = self.class.post("/_db/#{@database}/_api/gharial/#{@graph}/vertex", request)
101
- if @@async == "store"
102
- result.headers["x-arango-async-id"]
90
+ return result.headers["x-arango-async-id"] if @@async == "store"
91
+ result = result.parsed_response
92
+ if @@verbose
93
+ @orphanCollections << collection unless result["error"]
94
+ result
103
95
  else
104
- result = result.parsed_response
105
- if @@verbose
106
- result
107
- else
108
- if result["error"]
109
- result["errorMessage"]
110
- else
111
- @orphanCollections << collection
112
- self
113
- end
114
- end
96
+ return result["errorMessage"] if result["error"]
97
+ @orphanCollections << collection
98
+ self
115
99
  end
116
100
  end
117
101
 
118
102
  def removeVertexCollection(collection:) # TESTED
119
103
  collection = collection.is_a?(String) ? collection : collection.collection
120
104
  result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}/vertex/#{collection}", @@request)
121
- if @@async == "store"
122
- result.headers["x-arango-async-id"]
105
+ return result.headers["x-arango-async-id"] if @@async == "store"
106
+ result = result.parsed_response
107
+ if @@verbose
108
+ @orphanCollections -= [collection] unless result["error"]
109
+ result
123
110
  else
124
- result = result.parsed_response
125
- if @@verbose
126
- result
127
- else
128
- if result["error"]
129
- result["errorMessage"]
130
- else
131
- @orphanCollections -= [collection]
132
- self
133
- end
134
- end
111
+ return result["errorMessage"] if result["error"]
112
+ @orphanCollections -= [collection]
113
+ self
135
114
  end
136
115
  end
137
116
 
@@ -139,12 +118,9 @@ class ArangoGraph < ArangoServer
139
118
 
140
119
  def edgeCollections # TESTED
141
120
  result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}/edge", @@request)
142
- if @@async == "store"
143
- result.headers["x-arango-async-id"]
144
- else
145
- result = result.parsed_response
146
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["collections"].map{|x| ArangoCollection.new(collection: x)}
147
- end
121
+ return result.headers["x-arango-async-id"] if @@async == "store"
122
+ result = result.parsed_response
123
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["collections"].map{|x| ArangoCollection.new(collection: x)}
148
124
  end
149
125
 
150
126
  def addEdgeCollection(collection:, from:, to:, replace: false) # TESTED
@@ -156,32 +132,24 @@ class ArangoGraph < ArangoServer
156
132
  body["from"] = from.map{|f| f.is_a?(String) ? f : f.id }
157
133
  body["to"] = to.map{|t| t.is_a?(String) ? t : t.id }
158
134
  request = @@request.merge({ :body => body.to_json })
159
-
160
135
  if replace
161
136
  result = self.class.put("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{collection}", request)
162
137
  else
163
138
  result = self.class.post("/_db/#{@database}/_api/gharial/#{@graph}/edge", request)
164
139
  end
165
-
166
- if @@async == "store"
167
- result.headers["x-arango-async-id"]
168
- else
169
- result = result.parsed_response
170
- if @@verbose
171
- unless result["error"]
172
- @edgeDefinitions = result["graph"]["edgeDefinitions"]
173
- @orphanCollections = result["graph"]["orphanCollections"]
174
- end
175
- result
176
- else
177
- if result["error"]
178
- result["errorMessage"]
179
- else
180
- @edgeDefinitions = result["graph"]["edgeDefinitions"]
181
- @orphanCollections = result["graph"]["orphanCollections"]
182
- self
183
- end
140
+ return result.headers["x-arango-async-id"] if @@async == "store"
141
+ result = result.parsed_response
142
+ if @@verbose
143
+ unless result["error"]
144
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
145
+ @orphanCollections = result["graph"]["orphanCollections"]
184
146
  end
147
+ result
148
+ else
149
+ return result["errorMessage"] if result["error"]
150
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
151
+ @orphanCollections = result["graph"]["orphanCollections"]
152
+ self
185
153
  end
186
154
  end
187
155
 
@@ -192,26 +160,19 @@ class ArangoGraph < ArangoServer
192
160
  def removeEdgeCollection(collection:) # TESTED
193
161
  collection = collection.is_a?(String) ? collection : collection.collection
194
162
  result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{collection}", @@request)
195
-
196
- if @@async == "store"
197
- result.headers["x-arango-async-id"]
198
- else
199
- result = result.parsed_response
200
- if @@verbose
201
- unless result["error"]
202
- @edgeDefinitions = result["graph"]["edgeDefinitions"]
203
- @orphanCollections = result["graph"]["orphanCollections"]
204
- end
205
- result
206
- else
207
- if result["error"]
208
- result["errorMessage"]
209
- else
210
- @edgeDefinitions = result["graph"]["edgeDefinitions"]
211
- @orphanCollections = result["graph"]["orphanCollections"]
212
- self
213
- end
163
+ return result.headers["x-arango-async-id"] if @@async == "store"
164
+ result = result.parsed_response
165
+ if @@verbose
166
+ unless result["error"]
167
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
168
+ @orphanCollections = result["graph"]["orphanCollections"]
214
169
  end
170
+ result
171
+ else
172
+ return result["errorMessage"] if result["error"]
173
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
174
+ @orphanCollections = result["graph"]["orphanCollections"]
175
+ self
215
176
  end
216
177
  end
217
178
  end