ashikawa-core 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.hound.yml +1 -1
- data/.travis.yml +1 -5
- data/CHANGELOG.md +13 -0
- data/README.md +2 -3
- data/config/reek.yml +1 -0
- data/lib/ashikawa-core/collection.rb +14 -1
- data/lib/ashikawa-core/connection.rb +1 -0
- data/lib/ashikawa-core/database.rb +46 -3
- data/lib/ashikawa-core/document.rb +14 -1
- data/lib/ashikawa-core/edge.rb +6 -1
- data/lib/ashikawa-core/edge_collection.rb +92 -0
- data/lib/ashikawa-core/error_response.rb +16 -0
- data/lib/ashikawa-core/exceptions/client_error/resource_not_found/collection_not_in_graph.rb +18 -0
- data/lib/ashikawa-core/exceptions/client_error/resource_not_found/graph_not_found.rb +18 -0
- data/lib/ashikawa-core/faraday_factory.rb +1 -1
- data/lib/ashikawa-core/graph.rb +222 -0
- data/lib/ashikawa-core/version.rb +11 -1
- data/lib/ashikawa-core/vertex_collection.rb +35 -0
- data/lib/ashikawa-core/x_arango_version.rb +26 -0
- data/spec/acceptance/graph_spec.rb +89 -0
- data/spec/acceptance/spec_helper.rb +15 -2
- data/spec/unit/collection_spec.rb +23 -8
- data/spec/unit/connection_spec.rb +47 -0
- data/spec/unit/database_spec.rb +111 -0
- data/spec/unit/document_spec.rb +16 -0
- data/spec/unit/edge_collection_spec.rb +105 -0
- data/spec/unit/edge_spec.rb +23 -0
- data/spec/unit/exception_spec.rb +12 -0
- data/spec/unit/faraday_factory_spec.rb +1 -0
- data/spec/unit/graph_spec.rb +270 -0
- data/spec/unit/vertex_collection_spec.rb +48 -0
- metadata +17 -3
@@ -21,6 +21,19 @@ describe Ashikawa::Core::Connection do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
it 'should include include the x-arango-version header in each request' do
|
25
|
+
[:get, :post, :put, :delete].each do |http_verb|
|
26
|
+
request_stub.send(http_verb, '/_db/_system/_api/my/path') do |request|
|
27
|
+
expect(request[:request_headers][:'X-Arango-Version']).to eq '20200'
|
28
|
+
[200, response_headers, JSON.generate({ 'name' => 'dude' })]
|
29
|
+
end
|
30
|
+
|
31
|
+
subject.send_request 'my/path', http_verb => {}
|
32
|
+
|
33
|
+
request_stub.verify_stubbed_calls
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
24
37
|
it 'should send a get request' do
|
25
38
|
request_stub.get('/_db/_system/_api/my/path') do
|
26
39
|
[200, response_headers, JSON.generate({ 'name' => 'dude' })]
|
@@ -205,6 +218,40 @@ describe Ashikawa::Core::Connection do
|
|
205
218
|
request_stub.verify_stubbed_calls
|
206
219
|
end
|
207
220
|
|
221
|
+
context 'handle 404 in the gharial module' do
|
222
|
+
let(:request_url) { '/_db/_system/_api/gharial/vertex/42' }
|
223
|
+
|
224
|
+
it 'should raise GraphNotFoundException if the graph could not be found' do
|
225
|
+
request_stub.get(request_url) do
|
226
|
+
[404, response_headers, { 'errorMessage' => 'graph not found' }]
|
227
|
+
end
|
228
|
+
|
229
|
+
expect { subject.send_request 'gharial/vertex/42' }.to raise_error(Ashikawa::Core::GraphNotFoundException)
|
230
|
+
|
231
|
+
request_stub.verify_stubbed_calls
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should raise CollectionNotFoundException the collection could not be found' do
|
235
|
+
request_stub.get(request_url) do
|
236
|
+
[404, response_headers, { 'errorMessage' => 'collection not found' }]
|
237
|
+
end
|
238
|
+
|
239
|
+
expect { subject.send_request 'gharial/vertex/42' }.to raise_error(Ashikawa::Core::CollectionNotFoundException)
|
240
|
+
|
241
|
+
request_stub.verify_stubbed_calls
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should raise DocumentNotFoundException the document could not be found' do
|
245
|
+
request_stub.get(request_url) do
|
246
|
+
[404, response_headers, { 'errorMessage' => 'document not found' }]
|
247
|
+
end
|
248
|
+
|
249
|
+
expect { subject.send_request 'gharial/vertex/42' }.to raise_error(Ashikawa::Core::DocumentNotFoundException)
|
250
|
+
|
251
|
+
request_stub.verify_stubbed_calls
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
208
255
|
it 'should raise an exception for unknown pathes' do
|
209
256
|
request_stub.get('/_db/_system/_api/unknown_path/4590/333') do
|
210
257
|
[404, response_headers, '']
|
data/spec/unit/database_spec.rb
CHANGED
@@ -208,5 +208,116 @@ describe Ashikawa::Core::Database do
|
|
208
208
|
|
209
209
|
expect(subject.create_transaction(js_function, collections)).to be(transaction)
|
210
210
|
end
|
211
|
+
|
212
|
+
context 'managing graphs' do
|
213
|
+
let(:raw_graph) { double('RawGraph') }
|
214
|
+
let(:gharial_response) { double('GharialResponse') }
|
215
|
+
let(:graph) { instance_double(Ashikawa::Core::Graph) }
|
216
|
+
|
217
|
+
before do
|
218
|
+
allow(gharial_response).to receive(:[]).with('graph').and_return(raw_graph)
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should fetch a single graph if it exists' do
|
222
|
+
expect(connection).to receive(:send_request)
|
223
|
+
.with('gharial/my_awesome_graph')
|
224
|
+
.and_return(gharial_response)
|
225
|
+
|
226
|
+
expect(Ashikawa::Core::Graph).to receive(:new)
|
227
|
+
.with(subject, raw_graph)
|
228
|
+
.and_return(graph)
|
229
|
+
|
230
|
+
expect(subject.graph('my_awesome_graph')).to eq graph
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should create a single graph if it doesn't exist" do
|
234
|
+
expect(connection).to receive(:send_request).with('gharial/my_awesome_graph') do
|
235
|
+
raise Ashikawa::Core::GraphNotFoundException
|
236
|
+
end
|
237
|
+
|
238
|
+
expect(subject).to receive(:create_graph).with('my_awesome_graph').and_return(graph)
|
239
|
+
|
240
|
+
expect(subject.graph('my_awesome_graph')).to eq graph
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'should create a graph' do
|
244
|
+
expect(connection).to receive(:send_request)
|
245
|
+
.with('gharial', post: { name: 'my_awesome_graph' })
|
246
|
+
.and_return(gharial_response)
|
247
|
+
|
248
|
+
expect(Ashikawa::Core::Graph).to receive(:new)
|
249
|
+
.with(subject, raw_graph)
|
250
|
+
.and_return(graph)
|
251
|
+
|
252
|
+
expect(subject.create_graph('my_awesome_graph')).to eq graph
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should create a single graph with list of edge_definitions' do
|
256
|
+
create_params = {
|
257
|
+
name: 'my_awesome_graph',
|
258
|
+
edgeDefinitions: [
|
259
|
+
{ collection: 'visited', from: ['ponies'], to: ['places'] }
|
260
|
+
]
|
261
|
+
}
|
262
|
+
expect(connection).to receive(:send_request)
|
263
|
+
.with('gharial', post: create_params)
|
264
|
+
.and_return(gharial_response)
|
265
|
+
|
266
|
+
expect(Ashikawa::Core::Graph).to receive(:new)
|
267
|
+
.with(subject, raw_graph)
|
268
|
+
.and_return(graph)
|
269
|
+
|
270
|
+
options = {
|
271
|
+
edge_definitions: [
|
272
|
+
{
|
273
|
+
collection: 'visited',
|
274
|
+
from: ['ponies'],
|
275
|
+
to: ['places']
|
276
|
+
}
|
277
|
+
]
|
278
|
+
}
|
279
|
+
|
280
|
+
expect(subject.create_graph('my_awesome_graph', options)).to eq graph
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should create a single graph with list of orphan_collections' do
|
284
|
+
create_params = {
|
285
|
+
name: 'my_awesome_graph',
|
286
|
+
orphanCollections: ['i_am_alone']
|
287
|
+
}
|
288
|
+
expect(connection).to receive(:send_request)
|
289
|
+
.with('gharial', post: create_params)
|
290
|
+
.and_return(gharial_response)
|
291
|
+
|
292
|
+
expect(Ashikawa::Core::Graph).to receive(:new)
|
293
|
+
.with(subject, raw_graph)
|
294
|
+
.and_return(graph)
|
295
|
+
|
296
|
+
options = {
|
297
|
+
orphan_collections: ['i_am_alone']
|
298
|
+
}
|
299
|
+
|
300
|
+
expect(subject.create_graph('my_awesome_graph', options)).to eq graph
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'should fetch a list of all graphs in the database' do
|
305
|
+
raw_list_of_graphs = double('ListOfGraphs')
|
306
|
+
allow(raw_list_of_graphs).to receive(:[])
|
307
|
+
.with('graphs')
|
308
|
+
.and_return([raw_graph])
|
309
|
+
|
310
|
+
expect(connection).to receive(:send_request)
|
311
|
+
.with('gharial')
|
312
|
+
.and_return(raw_list_of_graphs)
|
313
|
+
|
314
|
+
expect(Ashikawa::Core::Graph).to receive(:new)
|
315
|
+
.with(subject, raw_graph)
|
316
|
+
.and_return(graph)
|
317
|
+
|
318
|
+
expect(subject.graphs).to eq [graph]
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
211
322
|
end
|
212
323
|
end
|
data/spec/unit/document_spec.rb
CHANGED
@@ -57,6 +57,22 @@ describe Ashikawa::Core::Document do
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
describe 'initialized with a garaph' do
|
61
|
+
let(:graph) { double('Ashikawa::Core::Graph', name: 'my-graph') }
|
62
|
+
let(:additional_data_with_graph) { { graph: graph, more_info: more_info } }
|
63
|
+
subject { Ashikawa::Core::Document.new(database, raw_data, additional_data_with_graph) }
|
64
|
+
|
65
|
+
its(['more_info']) { should eq(more_info) }
|
66
|
+
its(:graph) { should eq(graph) }
|
67
|
+
|
68
|
+
it 'should send requests through the graph module' do
|
69
|
+
expect(database).to receive(:send_request)
|
70
|
+
.with("gharial/my-graph/vertex/#{id}", {})
|
71
|
+
|
72
|
+
subject.send(:send_request_for_document, {})
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
60
76
|
describe 'initialized document with ID' do
|
61
77
|
subject { Ashikawa::Core::Document.new(database, raw_data) }
|
62
78
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'unit/spec_helper'
|
3
|
+
require 'ashikawa-core/edge_collection'
|
4
|
+
require 'ashikawa-core/document'
|
5
|
+
require 'ashikawa-core/graph'
|
6
|
+
require 'ashikawa-core/database'
|
7
|
+
|
8
|
+
describe Ashikawa::Core::EdgeCollection do
|
9
|
+
let(:database) { instance_double('Ashikawa::Core::Database') }
|
10
|
+
let(:raw_collection) do
|
11
|
+
{
|
12
|
+
'id' => '60768679',
|
13
|
+
'name' => 'relation',
|
14
|
+
'status' => 3,
|
15
|
+
'type' => 3,
|
16
|
+
'error' => false,
|
17
|
+
'code' => 200
|
18
|
+
}
|
19
|
+
end
|
20
|
+
let(:graph) { instance_double('Ashikawa::Core::Graph', name: 'my_graph') }
|
21
|
+
let(:new_edge) { instance_double('Ashikawa::Core::Edge') }
|
22
|
+
let(:raw_edge) { double('RawEdge') }
|
23
|
+
let(:post_response) { { 'edge' => { '_key' => '123' } } }
|
24
|
+
|
25
|
+
context 'an initialized edge collection' do
|
26
|
+
subject { Ashikawa::Core::EdgeCollection.new(database, raw_collection, graph) }
|
27
|
+
|
28
|
+
it 'should be a subclass of Collection' do
|
29
|
+
expect(subject).to be_kind_of Ashikawa::Core::Collection
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should have a reference to its graph' do
|
33
|
+
expect(subject.graph).to eq graph
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'adding edges' do
|
37
|
+
let(:this_document) { instance_double('Ashikawa::Core::Document', id: 'this_document_id') }
|
38
|
+
let(:that_document) { instance_double('Ashikawa::Core::Document', id: 'that_document_id') }
|
39
|
+
|
40
|
+
before do
|
41
|
+
allow(subject).to receive(:send_request)
|
42
|
+
.with('gharial/my_graph/edge/relation/', post: { _from: 'this_document_id', _to: 'that_document_id' })
|
43
|
+
.and_return(post_response)
|
44
|
+
|
45
|
+
allow(subject).to receive(:fetch)
|
46
|
+
.with('123')
|
47
|
+
.and_return(new_edge)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should add a directed relation between to vertices' do
|
51
|
+
expect(subject).to receive(:send_request)
|
52
|
+
.with('gharial/my_graph/edge/relation/', post: { _from: 'this_document_id', _to: 'that_document_id' })
|
53
|
+
.and_return(post_response)
|
54
|
+
|
55
|
+
subject.add(from: this_document, to: that_document)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should return the edge documents' do
|
59
|
+
created_edges = subject.add(from: this_document, to: that_document)
|
60
|
+
|
61
|
+
expect(created_edges).to eq new_edge
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'removing edges by example' do
|
66
|
+
let(:this_document) { instance_double('Ashikawa::Core::Document', id: 'this_document_id') }
|
67
|
+
let(:that_document) { instance_double('Ashikawa::Core::Document', id: 'that_document_id') }
|
68
|
+
let(:query) { double('Query') }
|
69
|
+
let(:aql_string) do
|
70
|
+
<<-AQL.gsub(/^[ \t]*/, '')
|
71
|
+
FOR e IN @@edge_collection
|
72
|
+
FILTER e._from == @from && e._to == @to
|
73
|
+
REMOVE e._key IN @@edge_collection
|
74
|
+
AQL
|
75
|
+
end
|
76
|
+
let(:bind_vars) { { :'@edge_collection' => 'relation', :from => 'this_document_id', :to => 'that_document_id' } }
|
77
|
+
|
78
|
+
before do
|
79
|
+
allow(database).to receive(:query).and_return(query)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should remove the edges' do
|
83
|
+
expect(query).to receive(:execute)
|
84
|
+
.with(aql_string, bind_vars: bind_vars)
|
85
|
+
|
86
|
+
subject.remove(from: this_document, to: that_document)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should overwrite #send_request_for_this_collection to use gharial' do
|
91
|
+
expect(subject).to receive(:send_request)
|
92
|
+
.with('gharial/my_graph/edge/relation/edge_key', {})
|
93
|
+
|
94
|
+
subject.send(:send_request_for_this_collection, 'edge_key')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should overwrite the #build_content_class to create edges with the graph attached' do
|
98
|
+
expect(Ashikawa::Core::Edge).to receive(:new)
|
99
|
+
.with(database, raw_edge, graph: graph)
|
100
|
+
.and_return(new_edge)
|
101
|
+
|
102
|
+
subject.build_content_class(raw_edge)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/spec/unit/edge_spec.rb
CHANGED
@@ -55,6 +55,13 @@ describe Ashikawa::Core::Edge do
|
|
55
55
|
subject['last_name'] = new_last_name
|
56
56
|
subject.save
|
57
57
|
end
|
58
|
+
|
59
|
+
it 'should send requests to the edge endpoint' do
|
60
|
+
expect(database).to receive(:send_request)
|
61
|
+
.with("edge/#{id}", {})
|
62
|
+
|
63
|
+
subject.send(:send_request_for_document, {})
|
64
|
+
end
|
58
65
|
end
|
59
66
|
|
60
67
|
describe 'initializing edge with additional data' do
|
@@ -63,5 +70,21 @@ describe Ashikawa::Core::Edge do
|
|
63
70
|
subject { Ashikawa::Core::Edge.new(database, raw_data, additional_data) }
|
64
71
|
|
65
72
|
its(['more_info']) { should eq(more_info) }
|
73
|
+
|
74
|
+
context 'initializing with a graph' do
|
75
|
+
let(:graph) { double('Ashikawa::Core::Graph', name: 'my-graph') }
|
76
|
+
let(:additional_data_with_graph) { { graph: graph, more_info: more_info } }
|
77
|
+
subject { Ashikawa::Core::Edge.new(database, raw_data, additional_data_with_graph) }
|
78
|
+
|
79
|
+
its(['more_info']) { should eq(more_info) }
|
80
|
+
its(:graph) { should eq(graph) }
|
81
|
+
|
82
|
+
it 'should send requests through the graph module' do
|
83
|
+
expect(database).to receive(:send_request)
|
84
|
+
.with("gharial/my-graph/edge/#{id}", {})
|
85
|
+
|
86
|
+
subject.send(:send_request_for_document, {})
|
87
|
+
end
|
88
|
+
end
|
66
89
|
end
|
67
90
|
end
|
data/spec/unit/exception_spec.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
require 'unit/spec_helper'
|
3
|
+
|
2
4
|
require 'ashikawa-core/exceptions/no_collection_provided'
|
3
5
|
require 'ashikawa-core/exceptions/client_error'
|
4
6
|
require 'ashikawa-core/exceptions/client_error/authentication_failed'
|
@@ -6,7 +8,9 @@ require 'ashikawa-core/exceptions/client_error/bad_syntax'
|
|
6
8
|
require 'ashikawa-core/exceptions/client_error/resource_not_found'
|
7
9
|
require 'ashikawa-core/exceptions/client_error/resource_not_found/document_not_found'
|
8
10
|
require 'ashikawa-core/exceptions/client_error/resource_not_found/collection_not_found'
|
11
|
+
require 'ashikawa-core/exceptions/client_error/resource_not_found/collection_not_in_graph'
|
9
12
|
require 'ashikawa-core/exceptions/client_error/resource_not_found/index_not_found'
|
13
|
+
require 'ashikawa-core/exceptions/client_error/resource_not_found/graph_not_found'
|
10
14
|
require 'ashikawa-core/exceptions/server_error'
|
11
15
|
require 'ashikawa-core/exceptions/server_error/json_error'
|
12
16
|
|
@@ -48,6 +52,14 @@ describe Ashikawa::Core::IndexNotFoundException do
|
|
48
52
|
its(:to_s) { should include 'does not exist' }
|
49
53
|
end
|
50
54
|
|
55
|
+
describe Ashikawa::Core::GraphNotFoundException do
|
56
|
+
its(:to_s) { should include 'does not exist' }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Ashikawa::Core::CollectionNotInGraphException do
|
60
|
+
its(:to_s) { should include 'not been added to the graph yet' }
|
61
|
+
end
|
62
|
+
|
51
63
|
describe Ashikawa::Core::ServerError do
|
52
64
|
let(:error_message) { 'The server is misbehaving' }
|
53
65
|
subject { Ashikawa::Core::ServerError.new(error_message) }
|
@@ -11,6 +11,7 @@ describe Ashikawa::Core::FaradayFactory do
|
|
11
11
|
before do
|
12
12
|
allow(Faraday).to receive(:new).with(api_string).and_yield(config_block)
|
13
13
|
allow(config_block).to receive(:request).with(:json)
|
14
|
+
allow(config_block).to receive(:request).with(:x_arango_version)
|
14
15
|
allow(config_block).to receive(:response).with(:error_response)
|
15
16
|
allow(config_block).to receive(:response).with(:json)
|
16
17
|
allow(config_block).to receive(:adapter).with(Faraday.default_adapter)
|
@@ -0,0 +1,270 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'unit/spec_helper'
|
3
|
+
require 'ashikawa-core/graph'
|
4
|
+
require 'ashikawa-core/document'
|
5
|
+
require 'ashikawa-core/database'
|
6
|
+
|
7
|
+
describe Ashikawa::Core::Graph do
|
8
|
+
let(:database) { instance_double('Ashikawa::Core::Database') }
|
9
|
+
let(:raw_graph) { double('RawGraph').as_null_object }
|
10
|
+
let(:edge_definition) do
|
11
|
+
{
|
12
|
+
'collection' => 'friends',
|
13
|
+
'from' => %w(ponies),
|
14
|
+
'to' => %w(dragons ponies)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def collection_double(name)
|
19
|
+
instance_double('Ashikawa::Core::VertexCollection', name: name.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
def edge_collection_double(name)
|
23
|
+
instance_double('Ashikawa::Core::EdgeCollection', name: name.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'an initialized graph' do
|
27
|
+
subject { Ashikawa::Core::Graph.new(database, raw_graph) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(raw_graph).to receive(:[]).with('name').and_return('my_graph')
|
31
|
+
allow(raw_graph).to receive(:[]).with('_rev').and_return('A113')
|
32
|
+
allow(raw_graph).to receive(:fetch).with('orphanCollections').and_return(['orphan'])
|
33
|
+
allow(raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([edge_definition])
|
34
|
+
end
|
35
|
+
|
36
|
+
its(:database) { should eq database }
|
37
|
+
its(:name) { should eq 'my_graph' }
|
38
|
+
its(:revision) { should eq 'A113' }
|
39
|
+
its(:edge_definitions) { should eq [edge_definition] }
|
40
|
+
|
41
|
+
it 'should delegate send_request to the database' do
|
42
|
+
expect(database).to receive(:send_request).with('gharial/my_graph')
|
43
|
+
|
44
|
+
subject.send_request 'gharial/my_graph'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should extract the name from the _key if no name was provided' do
|
48
|
+
allow(raw_graph).to receive(:[]).with('name').and_return(nil)
|
49
|
+
allow(raw_graph).to receive(:[]).with('_key').and_return('my_graph')
|
50
|
+
expect(subject.name).to eq 'my_graph'
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'finding neighbors' do
|
54
|
+
let(:some_document) { instance_double('Ashikawa::Core::Document', key: 'somekey') }
|
55
|
+
let(:query) { double('Query') }
|
56
|
+
let(:cursor) { double('Cursor') }
|
57
|
+
|
58
|
+
before do
|
59
|
+
allow(database).to receive(:query).and_return(query)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should return the cursor for the query' do
|
63
|
+
allow(query).to receive(:execute)
|
64
|
+
.and_return(cursor)
|
65
|
+
|
66
|
+
expect(subject.neighbors(some_document)).to eq cursor
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should run a neighbors AQL for all edge collections' do
|
70
|
+
aql_string = <<-AQL.gsub(/^[ \t]*/, '')
|
71
|
+
FOR n IN GRAPH_NEIGHBORS(@graph, { _key:@vertex_key }, {})
|
72
|
+
RETURN n.vertex
|
73
|
+
AQL
|
74
|
+
bind_vars = { graph: 'my_graph', vertex_key: 'somekey' }
|
75
|
+
|
76
|
+
expect(query).to receive(:execute)
|
77
|
+
.with(aql_string, bind_vars: bind_vars)
|
78
|
+
|
79
|
+
subject.neighbors(some_document)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should run a neighbors AQL for a specific edge collection' do
|
83
|
+
aql_string = <<-AQL.gsub(/^[ \t]*/, '')
|
84
|
+
FOR n IN GRAPH_NEIGHBORS(@graph, { _key:@vertex_key }, {edgeCollectionRestriction: @edge_collection})
|
85
|
+
RETURN n.vertex
|
86
|
+
AQL
|
87
|
+
bind_vars = { edge_collection: ['my-edges'], graph: 'my_graph', vertex_key: 'somekey' }
|
88
|
+
|
89
|
+
expect(query).to receive(:execute)
|
90
|
+
.with(aql_string, bind_vars: bind_vars)
|
91
|
+
|
92
|
+
subject.neighbors(some_document, edges: ['my-edges'])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'delete the graph' do
|
97
|
+
it 'should delete just the graph' do
|
98
|
+
expect(database).to receive(:send_request).with('gharial/my_graph', delete: { dropCollections: false })
|
99
|
+
|
100
|
+
subject.delete
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should delete the graph including all collections' do
|
104
|
+
expect(database).to receive(:send_request).with('gharial/my_graph', delete: { dropCollections: true })
|
105
|
+
|
106
|
+
subject.delete(drop_collections: true)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'vertex collections' do
|
111
|
+
let(:raw_vertex_collection) { double('RawVertexCollection') }
|
112
|
+
|
113
|
+
its(:vertex_collection_names) { should match_array %w(ponies dragons orphan) }
|
114
|
+
|
115
|
+
it 'should have a list of vertex collections' do
|
116
|
+
expected_vertex_collection = [
|
117
|
+
collection_double(:ponies),
|
118
|
+
collection_double(:orphan),
|
119
|
+
collection_double(:dragons)
|
120
|
+
]
|
121
|
+
allow(subject).to receive(:vertex_collection).and_return(*expected_vertex_collection)
|
122
|
+
|
123
|
+
expect(subject.vertex_collections).to match_array expected_vertex_collection
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should know if a collection has already been added to the list of vertices' do
|
127
|
+
allow(subject).to receive(:vertex_collection_names).and_return(['ponies'])
|
128
|
+
|
129
|
+
expect(subject.has_vertex_collection?('dragons')).to be_falsy
|
130
|
+
expect(subject.has_vertex_collection?('ponies')).to be_truthy
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'fetching a single collection' do
|
134
|
+
let(:existing_vertex_collection) { instance_double('Ashikawa::Core::VertexCollection') }
|
135
|
+
|
136
|
+
before do
|
137
|
+
allow(database).to receive(:send_request)
|
138
|
+
.with('collection/places')
|
139
|
+
.and_return(raw_vertex_collection)
|
140
|
+
|
141
|
+
allow(Ashikawa::Core::VertexCollection).to receive(:new)
|
142
|
+
.with(database, raw_vertex_collection, subject)
|
143
|
+
.and_return(existing_vertex_collection)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should get a single vertex collection' do
|
147
|
+
places_collection = subject.vertex_collection 'places'
|
148
|
+
expect(places_collection).to eq existing_vertex_collection
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'adding a collection' do
|
153
|
+
let(:updated_raw_graph) { double('UpdatedRawGraph') }
|
154
|
+
let(:new_vertex_collection) { instance_double('Ashikawa::Core::VertexCollection') }
|
155
|
+
|
156
|
+
before do
|
157
|
+
allow(updated_raw_graph).to receive(:[]).with('name').and_return('my_graph')
|
158
|
+
allow(updated_raw_graph).to receive(:[]).with('_rev')
|
159
|
+
allow(updated_raw_graph).to receive(:fetch).with('orphanCollections').and_return(['books'])
|
160
|
+
allow(updated_raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([edge_definition])
|
161
|
+
|
162
|
+
allow(database).to receive(:send_request)
|
163
|
+
.with('gharial/my_graph/vertex', post: { collection: 'books' })
|
164
|
+
.and_return({ 'graph' => updated_raw_graph })
|
165
|
+
|
166
|
+
allow(database).to receive(:send_request)
|
167
|
+
.with('collection/books')
|
168
|
+
.and_return(raw_vertex_collection)
|
169
|
+
|
170
|
+
allow(Ashikawa::Core::VertexCollection).to receive(:new)
|
171
|
+
.with(database, raw_vertex_collection, subject)
|
172
|
+
.and_return(new_vertex_collection)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should add the new collection to the vertex collections of the graph' do
|
176
|
+
books_collection = collection_double(:books)
|
177
|
+
allow(subject).to receive(:vertex_collection).and_return(books_collection)
|
178
|
+
|
179
|
+
subject.add_vertex_collection 'books'
|
180
|
+
|
181
|
+
expect(subject.vertex_collections).to include books_collection
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should return the newly created collection' do
|
185
|
+
expect(subject.add_vertex_collection('books')).to eq new_vertex_collection
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'edge collections' do
|
191
|
+
let(:raw_edge_collection) { double('RawEdgeCollection') }
|
192
|
+
|
193
|
+
its(:edge_collection_names) { should match_array %w(friends) }
|
194
|
+
|
195
|
+
it 'should have a list of edge collections' do
|
196
|
+
expected_edge_collections = [edge_collection_double(:friends)]
|
197
|
+
allow(subject).to receive(:edge_collection).and_return(*expected_edge_collections)
|
198
|
+
|
199
|
+
expect(subject.edge_collections).to match_array expected_edge_collections
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'fetching a single edge collections' do
|
203
|
+
let(:existing_edge_collection) { instance_double('Ashikawa::Core::EdgeCollection') }
|
204
|
+
|
205
|
+
before do
|
206
|
+
allow(database).to receive(:send_request)
|
207
|
+
.with('collection/friends')
|
208
|
+
.and_return(raw_edge_collection)
|
209
|
+
|
210
|
+
allow(Ashikawa::Core::EdgeCollection).to receive(:new)
|
211
|
+
.with(database, raw_edge_collection, subject)
|
212
|
+
.and_return(existing_edge_collection)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should return a single edge collection' do
|
216
|
+
friends_colection = subject.edge_collection :friends
|
217
|
+
expect(friends_colection).to eq existing_edge_collection
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context 'adding a definition' do
|
222
|
+
let(:updated_raw_graph) { double('UpdatedRawGraph') }
|
223
|
+
let(:new_edge_collection) { instance_double('Ashikawa::Core::EdgeCollection') }
|
224
|
+
let(:new_edge_definition) do
|
225
|
+
{
|
226
|
+
'collection' => 'authorship',
|
227
|
+
'from' => ['author'],
|
228
|
+
'to' => ['books']
|
229
|
+
}
|
230
|
+
end
|
231
|
+
|
232
|
+
before do
|
233
|
+
allow(updated_raw_graph).to receive(:[]).with('name').and_return('my_graph')
|
234
|
+
allow(updated_raw_graph).to receive(:[]).with('_rev')
|
235
|
+
allow(updated_raw_graph).to receive(:fetch).with('orphanCollections').and_return(['orphans'])
|
236
|
+
allow(updated_raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([edge_definition])
|
237
|
+
|
238
|
+
allow(database).to receive(:send_request)
|
239
|
+
.with('gharial/my_graph/edge', post: { collection: :authorship, from: [:author], to: [:books] })
|
240
|
+
.and_return({ 'graph' => updated_raw_graph })
|
241
|
+
|
242
|
+
allow(subject).to receive(:edge_collection).and_return(new_edge_collection)
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'should define the name and direction' do
|
246
|
+
expect(database).to receive(:send_request)
|
247
|
+
.with('gharial/my_graph/edge', post: { collection: :authorship, from: [:author], to: [:books] })
|
248
|
+
.and_return({ 'graph' => updated_raw_graph })
|
249
|
+
|
250
|
+
subject.add_edge_definition(:authorship, from: [:author], to: [:books])
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should add the definition to the collection edge collections' do
|
254
|
+
allow(updated_raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([
|
255
|
+
edge_definition,
|
256
|
+
new_edge_definition
|
257
|
+
])
|
258
|
+
|
259
|
+
subject.add_edge_definition(:authorship, from: [:author], to: [:books])
|
260
|
+
|
261
|
+
expect(subject.edge_collections).to include new_edge_collection
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'should return the edge collection' do
|
265
|
+
expect(subject.add_edge_definition(:authorship, from: [:author], to: [:books])).to eq new_edge_collection
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|