arangorb3 0.0.10

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/Document.rb ADDED
@@ -0,0 +1,346 @@
1
+ # ==== DOCUMENT ====
2
+
3
+ module Arango
4
+ class Document
5
+ include Arango::Helper_Error
6
+ include Arango::Helper_Return
7
+ include Arango::Collection_Return
8
+
9
+ def self.new(*args)
10
+ hash = args[0]
11
+ super unless hash.is_a?(Hash)
12
+ collection = hash[:collection]
13
+ if collection.is_a?(Arango::Collection) &&
14
+ collection.database.server.active_cache && !hash[:name].nil?
15
+ cache_name = "#{collection.database.name}/#{collection.name}/#{hash[:name]}"
16
+ cached = collection.database.server.cache.cache.dig(:document, cache_name)
17
+ if cached.nil?
18
+ hash[:cache_name] = cache_name
19
+ return super
20
+ else
21
+ body = hash[:body] || {}
22
+ [:rev, :from, :to].each{|k| body[:"_#{k}"] ||= hash[k]}
23
+ body[:"_key"] ||= hash[:name]
24
+ cached.assign_attributes(body)
25
+ return cached
26
+ end
27
+ end
28
+ super
29
+ end
30
+
31
+ def initialize(name: nil, collection:, body: {}, rev: nil, from: nil,
32
+ to: nil, cache_name: nil)
33
+ assign_collection(collection)
34
+ unless cache_name.nil?
35
+ @cache_name = cache_name
36
+ @server.cache.save(:document, cache_name, self)
37
+ end
38
+ body[:_key] ||= name
39
+ body[:_rev] ||= rev
40
+ body[:_to] ||= to
41
+ body[:_from] ||= from
42
+ body[:_id] ||= "#{@collection.name}/#{name}" unless name.nil?
43
+ assign_attributes(body)
44
+ end
45
+
46
+ def name
47
+ return @body[:_key]
48
+ end
49
+ alias key name
50
+
51
+ def rev
52
+ return @body[:_rev]
53
+ end
54
+
55
+ def id
56
+ return @body[:_id]
57
+ end
58
+
59
+ def name=(att)
60
+ assign_attributes({_key: att})
61
+ end
62
+ alias key= name=
63
+
64
+ def rev=(att)
65
+ assign_attributes({_rev: att})
66
+ end
67
+
68
+ def id=(att)
69
+ assign_attributes({_id: id})
70
+ end
71
+
72
+ def from=(att)
73
+ att = att.id if att.is_a?(Arango::Document)
74
+ assign_attributes({_from: att})
75
+ end
76
+
77
+ def to=(att)
78
+ att = att.id if att.is_a?(Arango::Document)
79
+ assign_attributes({_to: att})
80
+ end
81
+
82
+ # === DEFINE ==
83
+
84
+ attr_reader :collection, :graph, :database, :server, :body, :cache_name
85
+
86
+ def body=(result)
87
+ result.delete_if{|k,v| v.nil?}
88
+ @body ||= {}
89
+ # binding.pry if @body[:_key] == "Second_Key"
90
+ hash = {
91
+ "_key": @body[:_key],
92
+ "_id": @body[:_id],
93
+ "_rev": @body[:_rev],
94
+ "_from": @body[:_from],
95
+ "_to": @body[:_to]
96
+ }
97
+ @body = hash.merge(result)
98
+ if @body[:_id].nil? && !@body[:_key].nil?
99
+ @body[:_id] = "#{@collection.name}/#{@body[:_key]}"
100
+ end
101
+ set_up_from_or_to("from", result[:_from])
102
+ set_up_from_or_to("to", result[:_to])
103
+ if @server.active_cache && @cache_name.nil? && !@body[:_id].nil?
104
+ @cache_name = "#{@database.name}/#{@body[:_id]}"
105
+ @server.cache.save(:document, @cache_name, self)
106
+ end
107
+ end
108
+ alias assign_attributes body=
109
+
110
+ # === TO HASH ===
111
+
112
+ def to_h
113
+ {
114
+ "name": @body[:_key],
115
+ "id": @body[:_id],
116
+ "rev": @body[:_rev],
117
+ "from": @body[:_from],
118
+ "to": @body[:_to],
119
+ "body": @body,
120
+ "cache_name": @cache_name,
121
+ "collection": @collection.name,
122
+ "graph": @graph&.name
123
+ }.delete_if{|k,v| v.nil?}
124
+ end
125
+
126
+ def set_up_from_or_to(attrs, var)
127
+ case var
128
+ when NilClass
129
+ @body[:"_#{attrs}"] = nil
130
+ when String
131
+ unless var.include?("/")
132
+ raise Arango::Error.new err: :attribute_is_not_valid, data:
133
+ {"attribute": attrs, "wrong_value": var}
134
+ end
135
+ @body[:"_#{attrs}"] = var
136
+ when Arango::Document
137
+ @body[:"_#{attrs}"] = var.id
138
+ @from = var if attrs == "from"
139
+ @to = var if attrs == "to"
140
+ else
141
+ raise Arango::Error.new err: :attribute_is_not_valid, data:
142
+ {"attribute": attrs, "wrong_value": var}
143
+ end
144
+ end
145
+ private :set_up_from_or_to
146
+
147
+ def from(string: false)
148
+ return @body[:_from] if string
149
+ @from ||= retrieve_instance_from_and_to(@body[:_from])
150
+ return @from
151
+ end
152
+
153
+ def to(string: false)
154
+ return @body[:_to] if string
155
+ @to ||= retrieve_instance_from_and_to(@body[:_to])
156
+ return @to
157
+ end
158
+
159
+ def retrieve_instance_from_and_to(var)
160
+ case var
161
+ when NilClass
162
+ return nil
163
+ when String
164
+ collection_name, document_name = var.split("/")
165
+ collection = Arango::Collection.new name: collection_name, database: @database
166
+ if @graph.nil?
167
+ return Arango::Document.new(name: document_name, collection: collection)
168
+ else
169
+ collection.graph = @graph
170
+ return Arango::Vertex.new(name: document_name, collection: collection)
171
+ end
172
+ end
173
+ end
174
+ private :retrieve_instance_from_and_to
175
+
176
+ # == GET ==
177
+
178
+ def retrieve(if_none_match: false, if_match: false)
179
+ headers = {}
180
+ headers[:"If-None-Match"] = @body[:_rev] if if_none_match
181
+ headers[:"If-Match"] = @body[:_rev] if if_match
182
+ result = @database.request("GET", "_api/document/#{@body[:_id]}", headers: headers)
183
+ return_element(result)
184
+ end
185
+
186
+ # == HEAD ==
187
+
188
+ def head(if_none_match: false, if_match: false)
189
+ headers = {}
190
+ headers[:"If-None-Match"] = @body[:_rev] if if_none_match
191
+ headers[:"If-Match"] = @body[:_rev] if if_match
192
+ @database.request("HEAD", "_api/document/#{@body[:_id]}", headers: headers)
193
+ end
194
+
195
+ # == POST ==
196
+
197
+ def create(body: {}, waitForSync: nil, returnNew: nil, silent: nil)
198
+ body = @body.merge(body)
199
+ query = {
200
+ "waitForSync": waitForSync,
201
+ "returnNew": returnNew,
202
+ "silent": silent
203
+ }
204
+ result = @database.request("POST", "_api/document/#{@collection.name}", body: body,
205
+ query: query)
206
+ return result if @server.async != false || silent
207
+ body2 = result.clone
208
+ if returnNew
209
+ body2.delete(:new)
210
+ body2 = body2.merge(result[:new])
211
+ end
212
+ body = body.merge(body2)
213
+ assign_attributes(body)
214
+ return return_directly?(result) ? result : self
215
+ end
216
+
217
+ # == PUT ==
218
+
219
+ def replace(body: {}, waitForSync: nil, ignoreRevs: nil, returnOld: nil,
220
+ returnNew: nil, silent: nil, if_match: false)
221
+ query = {
222
+ "waitForSync": waitForSync,
223
+ "returnNew": returnNew,
224
+ "returnOld": returnOld,
225
+ "ignoreRevs": ignoreRevs,
226
+ "silent": silent
227
+ }
228
+ headers = {}
229
+ headers[:"If-Match"] = @body[:_rev] if if_match
230
+ result = @database.request("PUT", "_api/document/#{@body[:_id]}", body: body,
231
+ query: query, headers: headers)
232
+ return result if @server.async != false || silent
233
+ body2 = result.clone
234
+ if returnNew
235
+ body2.delete(:new)
236
+ body2 = body2.merge(result[:new])
237
+ end
238
+ body = body.merge(body2)
239
+ assign_attributes(body)
240
+ return return_directly?(result) ? result : self
241
+ end
242
+
243
+ def update(body: {}, waitForSync: nil, ignoreRevs: nil,
244
+ returnOld: nil, returnNew: nil, keepNull: nil,
245
+ mergeObjects: nil, silent: nil, if_match: false)
246
+ query = {
247
+ "waitForSync": waitForSync,
248
+ "returnNew": returnNew,
249
+ "returnOld": returnOld,
250
+ "ignoreRevs": ignoreRevs,
251
+ "keepNull": keepNull,
252
+ "mergeObjects": mergeObjects,
253
+ "silent": silent
254
+ }
255
+ headers = {}
256
+ headers[:"If-Match"] = @body[:_rev] if if_match
257
+ result = @database.request("PATCH", "_api/document/#{@body[:_id]}", body: body,
258
+ query: query, headers: headers, keepNull: keepNull)
259
+ return result if @server.async != false || silent
260
+ body2 = result.clone
261
+ if returnNew
262
+ body2.delete(:new)
263
+ body2 = body2.merge(result[:new])
264
+ end
265
+ body = body.merge(body2)
266
+ if mergeObjects
267
+ @body = @body.merge(body)
268
+ else
269
+ body.each{|key, value| @body[key] = value}
270
+ end
271
+ assign_attributes(@body)
272
+ return return_directly?(result) ? result : self
273
+ end
274
+
275
+ # === DELETE ===
276
+
277
+ def destroy(waitForSync: nil, silent: nil, returnOld: nil, if_match: false)
278
+ query = {
279
+ "waitForSync": waitForSync,
280
+ "returnOld": returnOld,
281
+ "silent": silent
282
+ }
283
+ headers = {}
284
+ headers[:"If-Match"] = @body[:_rev] if if_match
285
+ result = @database.request("DELETE", "_api/document/#{@body[:_id]}", query: query,
286
+ headers: headers)
287
+ return result if @server.async != false || silent
288
+ body2 = result.clone
289
+ if returnOld
290
+ body2.delete(:old)
291
+ body2 = body2.merge(result[:old])
292
+ else
293
+ body2 = body2.merge(@body)
294
+ end
295
+ return_element(body2)
296
+ return true
297
+ end
298
+
299
+ # === EDGE ===
300
+
301
+ def edges(collection:, direction: nil)
302
+ satisfy_class?(collection, [Arango::Collection, String])
303
+ collection = collection.is_a?(Arango::Collection) ? collection.name : collection
304
+ query = {
305
+ "vertex": @body[:_id],
306
+ "direction": direction
307
+ }
308
+ result = @database.request("GET", "_api/edges/#{collection}", query: query)
309
+ return result if return_directly?(result)
310
+ result[:edges].map do |edge|
311
+ collection_name, key = edge[:_id].split("/")
312
+ collection = Arango::Collection.new(name: collection_name,
313
+ database: @database, type: :edge)
314
+ Arango::Document.new(name: key, body: edge, collection: collection)
315
+ end
316
+ end
317
+
318
+ def any(collection)
319
+ edges(collection: collection)
320
+ end
321
+
322
+ def out(collection)
323
+ edges(collection: collection, direction: "out")
324
+ end
325
+
326
+ def in(collection)
327
+ edges(collection: collection, direction: "in")
328
+ end
329
+
330
+ # === TRAVERSAL ===
331
+
332
+ def traversal(body: {}, sort: nil, direction: nil, minDepth: nil,
333
+ visitor: nil, itemOrder: nil, strategy: nil,
334
+ filter: nil, init: nil, maxIterations: nil, maxDepth: nil,
335
+ uniqueness: nil, order: nil, expander: nil,
336
+ edgeCollection: nil)
337
+ Arango::Traversal.new(body: body,
338
+ sort: sort, direction: direction, minDepth: minDepth,
339
+ vertex: self, visitor: visitor,itemOrder: itemOrder,
340
+ strategy: strategy, filter: filter, init: init,
341
+ maxIterations: maxIterations, maxDepth: maxDepth,
342
+ uniqueness: uniqueness, order: order,
343
+ expander: expander, edgeCollection: edgeCollection)
344
+ end
345
+ end
346
+ end
data/lib/Edge.rb ADDED
@@ -0,0 +1,104 @@
1
+ # === GRAPH VERTEX ===
2
+
3
+ module Arango
4
+ class Edge < Arango::Document
5
+ def initialize(name: nil, collection:, body: {}, rev: nil, from: nil,
6
+ to: nil)
7
+ assign_collection(collection)
8
+ body[:_key] ||= name
9
+ body[:_rev] ||= rev
10
+ body[:_from] ||= from
11
+ body[:_to] ||= to
12
+ body[:_id] ||= "#{@collection.name}/#{name}" unless name.nil?
13
+ assign_attributes(body)
14
+ end
15
+
16
+ # === DEFINE ===
17
+
18
+ attr_reader :collection, :database, :server, :graph
19
+
20
+ def collection=(collection)
21
+ satisfy_class?(collection, [Arango::Collection])
22
+ if collection.graph.nil?
23
+ raise Arango::Error.new err: :collection_does_not_have_a_graph, data:
24
+ {"name_collection": collection.name, "graph": nil}
25
+ end
26
+ @collection = collection
27
+ @graph = @collection.graph
28
+ @database = @collection.database
29
+ @server = @database.server
30
+ end
31
+ alias assign_collection collection=
32
+
33
+ # == GET ==
34
+
35
+ def retrieve(if_match: false)
36
+ headers = {}
37
+ headers[:"If-Match"] = @body[:_rev] if if_match
38
+ result = @graph.request("GET", "edge/#{@collection.name}/#{@body[:_key]}",
39
+ headers: headers, key: :edge)
40
+ return_element(result)
41
+ end
42
+
43
+ # == POST ==
44
+
45
+ def create(body: {}, waitForSync: nil)
46
+ body = @body.merge(body)
47
+ query = {
48
+ "waitForSync": waitForSync,
49
+ "_from": @body[:_from],
50
+ "_to": @body[:_to]
51
+ }
52
+ result = @graph.request("POST", "edge/#{@collection.name}", body: body,
53
+ query: query, key: :edge)
54
+ return result if @server.async != false
55
+ body2 = result.clone
56
+ body = body.merge(body2)
57
+ assign_attributes(body)
58
+ return return_directly?(result) ? result : self
59
+ end
60
+
61
+ # == PUT ==
62
+
63
+ def replace(body: {}, waitForSync: nil, keepNull: nil, if_match: false)
64
+ query = {
65
+ "waitForSync": waitForSync,
66
+ "keepNull": keepNull
67
+ }
68
+ headers = {}
69
+ headers[:"If-Match"] = @body[:_rev] if if_match
70
+ result = @graph.request("PUT", "edge/#{@collection.name}/#{@body[:_key]}",
71
+ body: body, query: query, headers: headers, key: :edge)
72
+ return result if @server.async != false
73
+ body2 = result.clone
74
+ body = body.merge(body2)
75
+ assign_attributes(body)
76
+ return return_directly?(result) ? result : self
77
+ end
78
+
79
+ def update(body: {}, waitForSync: nil, if_match: false)
80
+ query = {"waitForSync": waitForSync}
81
+ headers = {}
82
+ headers[:"If-Match"] = @body[:_rev] if if_match
83
+ result = @graph.request("PATCH", "edge/#{@collection.name}/#{@body[:_key]}",
84
+ body: body, query: query, headers: headers, key: :edge)
85
+ return result if @server.async != false
86
+ body2 = result.clone
87
+ body = body.merge(body2)
88
+ body = @body.merge(body)
89
+ assign_attributes(body)
90
+ return return_directly?(result) ? result : self
91
+ end
92
+
93
+ # === DELETE ===
94
+
95
+ def destroy(waitForSync: nil, if_match: false)
96
+ query = {"waitForSync": waitForSync}
97
+ headers = {}
98
+ headers[:"If-Match"] = @body[:_rev] if if_match
99
+ result = @graph.request("DELETE", "edge/#{@collection.name}/#{@body[:_key]}",
100
+ query: query, headers: headers)
101
+ return_delete(result)
102
+ end
103
+ end
104
+ end
data/lib/Error.rb ADDED
@@ -0,0 +1,125 @@
1
+ # === ERROR ===
2
+
3
+ module Arango
4
+ class Error < StandardError
5
+ @@list_arango_rb_errors = {
6
+ no_other_aql_next: {
7
+ code: 10001, message: "No other values with AQL next"
8
+ },
9
+ no_other_simple_next: {
10
+ code: 10002, message: "No other values with AQL next"
11
+ },
12
+ is_a_edge_collection: {
13
+ code: 10003, message: "This collection is an Edge collection"
14
+ },
15
+ is_a_document_collection: {
16
+ code: 10004, message: "This collection is a Document collection"
17
+ },
18
+ database_graph_no_same_as_collection_database: {
19
+ code: 10005, message: "Database of graph is not the same as the class"
20
+ },
21
+ wrong_type_instead_of_expected_one: {
22
+ code: 10006, message: "Expected a type, received another"
23
+ },
24
+ no_other_export_next: {
25
+ code: 10007, message: "No other values with AQL next"
26
+ },
27
+ no_aql_id_available: {
28
+ code: 10008, message: "AQL does not have id. It could have already been killed"
29
+ },
30
+ id_is_not_valid: {
31
+ code: 10009, message: "Given attribute is not a valid document id or an Arango::Document"
32
+ },
33
+ collection_does_not_have_a_graph: {
34
+ code: 10010, message: "Collection does not have a graph"
35
+ },
36
+ arangodb_did_not_return_a_valid_result: {
37
+ code: 10011, message: "ArangoDB didn't return a valid result"
38
+ },
39
+ read_or_write_should_be_string_or_collections: {
40
+ code: 10012, message: "read or write should be an array of name classes or Arango::Collections"
41
+ },
42
+ wrong_class: {
43
+ code: 10013, message: "Wrong class"
44
+ },
45
+ wrong_element: {
46
+ code: 10014, message: "Element is not part of the list"
47
+ },
48
+ orphan_collection_used_by_edge_definition: {
49
+ code: 10015, message: "Orphan collection is already used by an edge definition"
50
+ },
51
+ impossible_to_parse_arangodb_response: {
52
+ code: 10016, message: "Impossible to parse ArangoDB response"
53
+ },
54
+ batch_query_not_valid: {
55
+ code: 10017, message: "Query is not valid"
56
+ },
57
+ arangorb_didnt_return_a_valid_result: {
58
+ code: 10018, message: "ArangoRB didn't return a valid result"
59
+ },
60
+ impossible_to_connect_with_database: {
61
+ code: 10019, message: "Impossible to connect with database"
62
+ },
63
+ you_cannot_assign_from_or_to_to_a_vertex: {
64
+ code: 10020, message: "You cannot assign from or to to a Vertex"
65
+ },
66
+ wrong_start_vertex_type: {
67
+ code: 10021, message: "Starting vertex should be an Arango::Vertex, an Arango::Document (not Edge) or a valid vertex id"
68
+ },
69
+ database_undefined_for_traversal: {
70
+ code: 10022, message: "Database undefined for traversal"
71
+ },
72
+ edge_collection_should_be_of_type_edge: {
73
+ code: 10022, message: "Database undefined for traversal"
74
+ }
75
+ }
76
+
77
+ def initialize(err:, data: nil, skip_assignment: false)
78
+ unless skip_assignment
79
+ @message = @@list_arango_rb_errors[err][:message]
80
+ @code = @@list_arango_rb_errors[err][:code]
81
+ @internal_code = err
82
+ @data = data
83
+ end
84
+ super(@message)
85
+ end
86
+ attr_reader :data, :code, :message
87
+
88
+ def to_h
89
+ {
90
+ "message": @message,
91
+ "code": @code,
92
+ "data": @data,
93
+ "internal_code": @internal_code
94
+ }.delete_if{|k,v| v.nil?}
95
+ end
96
+ end
97
+ end
98
+
99
+ module Arango
100
+ class ErrorDB < Arango::Error
101
+ def initialize(message:, code:, data:, errorNum:, action:, url:, request:)
102
+ @message = message
103
+ @code = code
104
+ @data = data
105
+ @errorNum = errorNum
106
+ @action = action
107
+ @url = url
108
+ @request = request
109
+ super(err: nil, skip_assignment: true)
110
+ end
111
+ attr_reader :message, :code, :data, :errorNum, :action, :url, :request
112
+
113
+ def to_h
114
+ {
115
+ "action": @action,
116
+ "url": @url,
117
+ "request": @request,
118
+ "message": @message,
119
+ "code": @code,
120
+ "data": @data,
121
+ "errorNum": @errorNum
122
+ }.delete_if{|k,v| v.nil?}
123
+ end
124
+ end
125
+ end