guacamole 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +1 -1
- data/.travis.yml +16 -15
- data/CHANGELOG.md +16 -0
- data/GOALS.md +8 -0
- data/Guardfile +4 -0
- data/README.md +21 -81
- data/guacamole.gemspec +3 -3
- data/lib/guacamole.rb +1 -0
- data/lib/guacamole/aql_query.rb +6 -1
- data/lib/guacamole/collection.rb +34 -66
- data/lib/guacamole/configuration.rb +53 -25
- data/lib/guacamole/document_model_mapper.rb +149 -38
- data/lib/guacamole/edge.rb +74 -0
- data/lib/guacamole/edge_collection.rb +91 -0
- data/lib/guacamole/exceptions.rb +0 -5
- data/lib/guacamole/graph_query.rb +31 -0
- data/lib/guacamole/model.rb +4 -0
- data/lib/guacamole/proxies/proxy.rb +7 -3
- data/lib/guacamole/proxies/relation.rb +22 -0
- data/lib/guacamole/railtie.rb +1 -1
- data/lib/guacamole/transaction.rb +177 -0
- data/lib/guacamole/version.rb +1 -1
- data/shared/transaction.js +66 -0
- data/spec/acceptance/aql_spec.rb +32 -40
- data/spec/acceptance/relations_spec.rb +239 -0
- data/spec/acceptance/spec_helper.rb +2 -2
- data/spec/fabricators/author_fabricator.rb +2 -0
- data/spec/setup/arangodb.sh +2 -2
- data/spec/unit/collection_spec.rb +20 -97
- data/spec/unit/configuration_spec.rb +73 -50
- data/spec/unit/document_model_mapper_spec.rb +84 -77
- data/spec/unit/edge_collection_spec.rb +174 -0
- data/spec/unit/edge_spec.rb +57 -0
- data/spec/unit/proxies/relation_spec.rb +35 -0
- metadata +22 -14
- data/lib/guacamole/proxies/referenced_by.rb +0 -15
- data/lib/guacamole/proxies/references.rb +0 -15
- data/spec/acceptance/association_spec.rb +0 -40
- data/spec/unit/example_spec.rb +0 -8
@@ -81,6 +81,57 @@ describe Guacamole::Configuration do
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
describe 'graph' do
|
85
|
+
let(:database) { instance_double('Ashikawa::Core::Database') }
|
86
|
+
let(:graph) { instance_double('Ashikawa::Core::Graph') }
|
87
|
+
let(:graph_name) { 'my-amazing-graph' }
|
88
|
+
|
89
|
+
before do
|
90
|
+
subject.graph_name = nil
|
91
|
+
allow(subject).to receive(:database).and_return(database)
|
92
|
+
allow(database).to receive(:graph).with(graph_name).and_return(graph)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should allow access to the associated graph based on the graph_name attribute' do
|
96
|
+
allow(subject).to receive(:graph_name).and_return(graph_name)
|
97
|
+
|
98
|
+
expect(subject.graph).to eq graph
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'configure the graph name' do
|
102
|
+
context 'within a Rails application' do
|
103
|
+
let(:rails_module) { double('Rails') }
|
104
|
+
let(:application_class) { double('ApplicationClass', name: 'MyAwesomeApp::Application') }
|
105
|
+
let(:rails_application) { double('MyAwesomeApp::Application', class: application_class) }
|
106
|
+
|
107
|
+
before do
|
108
|
+
allow(rails_module).to receive(:application).and_return(rails_application)
|
109
|
+
stub_const('Rails', rails_module)
|
110
|
+
end
|
111
|
+
|
112
|
+
its(:graph_name) { should eq 'my_awesome_app_graph' }
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should be generated based on the current database name' do
|
116
|
+
allow(database).to receive(:name).and_return('my_database')
|
117
|
+
|
118
|
+
expect(subject.graph_name).to eq 'my_database_graph'
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should use a custom set graph name' do
|
122
|
+
subject.graph_name = 'fabulous_graph'
|
123
|
+
|
124
|
+
expect(subject.graph_name).to eq 'fabulous_graph'
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should take the graph name from the ENV' do
|
128
|
+
allow(ENV).to receive(:[]).with('GUACAMOLE_GRAPH').and_return('graph_from_env')
|
129
|
+
|
130
|
+
expect(subject.graph_name).to eq 'graph_from_env'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
84
135
|
describe 'build_config' do
|
85
136
|
context 'from a hash' do
|
86
137
|
let(:config_hash) do
|
@@ -90,47 +141,29 @@ describe Guacamole::Configuration do
|
|
90
141
|
'port' => 8529,
|
91
142
|
'username' => 'username',
|
92
143
|
'password' => 'password',
|
93
|
-
'database' => 'awesome_db'
|
144
|
+
'database' => 'awesome_db',
|
145
|
+
'graph' => 'custom_graph'
|
94
146
|
}
|
95
147
|
end
|
96
|
-
let(:config_struct) { subject.build_config(config_hash) }
|
97
|
-
|
98
|
-
it 'should create a struct with a database URL' do
|
99
|
-
expect(config_struct.url).to eq 'http://localhost:8529'
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'should create a struct with a username' do
|
103
|
-
expect(config_struct.username).to eq 'username'
|
104
|
-
end
|
105
148
|
|
106
|
-
|
107
|
-
expect(config_struct.password).to eq 'password'
|
108
|
-
end
|
149
|
+
subject { Guacamole::Configuration.build_config(config_hash) }
|
109
150
|
|
110
|
-
|
111
|
-
|
112
|
-
|
151
|
+
its(:url) { should eq 'http://localhost:8529' }
|
152
|
+
its(:username) { should eq 'username' }
|
153
|
+
its(:password) { should eq 'password' }
|
154
|
+
its(:database) { should eq 'awesome_db' }
|
155
|
+
its(:graph) { should eq 'custom_graph' }
|
113
156
|
end
|
114
157
|
|
115
158
|
context 'from a URL' do
|
116
159
|
let(:database_url) { 'http://username:password@localhost:8529/_db/awesome_db' }
|
117
|
-
let(:config_struct) { subject.build_config(database_url) }
|
118
|
-
|
119
|
-
it 'should create a struct with a database URL' do
|
120
|
-
expect(config_struct.url).to eq 'http://localhost:8529'
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'should create a struct with a username' do
|
124
|
-
expect(config_struct.username).to eq 'username'
|
125
|
-
end
|
126
160
|
|
127
|
-
|
128
|
-
expect(config_struct.password).to eq 'password'
|
129
|
-
end
|
161
|
+
subject { Guacamole::Configuration.build_config(database_url) }
|
130
162
|
|
131
|
-
|
132
|
-
|
133
|
-
|
163
|
+
its(:url) { should eq 'http://localhost:8529' }
|
164
|
+
its(:username) { should eq 'username' }
|
165
|
+
its(:password) { should eq 'password' }
|
166
|
+
its(:database) { should eq 'awesome_db' }
|
134
167
|
end
|
135
168
|
end
|
136
169
|
|
@@ -178,8 +211,9 @@ describe Guacamole::Configuration do
|
|
178
211
|
allow(subject).to receive(:create_database_connection)
|
179
212
|
allow(subject).to receive(:process_file_with_erb).with('config_file.yml')
|
180
213
|
allow(subject).to receive(:build_config).and_return(config_struct)
|
181
|
-
allow(config).to
|
182
|
-
allow(
|
214
|
+
allow(config).to receive(:[]).with('development').and_return(env_config)
|
215
|
+
allow(config_struct).to receive(:graph).and_return('custom_graph_name')
|
216
|
+
allow(YAML).to receive(:load).and_return(config)
|
183
217
|
end
|
184
218
|
|
185
219
|
it 'should parse a YAML configuration' do
|
@@ -206,6 +240,12 @@ describe Guacamole::Configuration do
|
|
206
240
|
subject.load 'config_file.yml'
|
207
241
|
end
|
208
242
|
|
243
|
+
it 'should set the graph name as read from the YAML file' do
|
244
|
+
expect(subject).to receive(:graph_name=).with('custom_graph_name')
|
245
|
+
|
246
|
+
subject.load 'config_file.yml'
|
247
|
+
end
|
248
|
+
|
209
249
|
it 'should warn if the database was not found' do
|
210
250
|
allow(subject).to receive(:database).and_return(double('Database'))
|
211
251
|
allow(subject.database).to receive(:name)
|
@@ -270,21 +310,4 @@ development:
|
|
270
310
|
subject.configure_with_uri(connection_uri)
|
271
311
|
end
|
272
312
|
end
|
273
|
-
|
274
|
-
describe 'experimental_features' do
|
275
|
-
let(:fresh_config) { Guacamole::Configuration.new }
|
276
|
-
|
277
|
-
after do
|
278
|
-
subject.experimental_features = []
|
279
|
-
end
|
280
|
-
|
281
|
-
it 'should default to none' do
|
282
|
-
expect(fresh_config.experimental_features).to be_empty
|
283
|
-
end
|
284
|
-
|
285
|
-
it 'should accept a list of features to activate' do
|
286
|
-
subject.experimental_features = [:aql_support]
|
287
|
-
expect(subject.experimental_features).to include :aql_support
|
288
|
-
end
|
289
|
-
end
|
290
313
|
end
|
@@ -22,6 +22,22 @@ describe Guacamole::DocumentModelMapper do
|
|
22
22
|
expect(mapper.model_class).to eq FancyModel
|
23
23
|
end
|
24
24
|
|
25
|
+
context 'document mapper instance' do
|
26
|
+
subject { Guacamole::DocumentModelMapper.new FancyModel, FakeIdentityMap }
|
27
|
+
|
28
|
+
let(:model) { double('Model') }
|
29
|
+
let(:model_class) { double('ModelClass') }
|
30
|
+
|
31
|
+
before do
|
32
|
+
allow(subject).to receive(:model_class).and_return(model_class)
|
33
|
+
allow(model).to receive(:instance_of?).with(model_class).and_return(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should know if it responsible for a certain model' do
|
37
|
+
expect(subject.responsible_for?(model)).to be_truthy
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
25
41
|
describe 'document_to_model' do
|
26
42
|
subject { Guacamole::DocumentModelMapper.new FancyModel, FakeIdentityMap }
|
27
43
|
|
@@ -52,57 +68,41 @@ describe Guacamole::DocumentModelMapper do
|
|
52
68
|
subject.document_to_model document
|
53
69
|
end
|
54
70
|
|
55
|
-
context 'with
|
56
|
-
let(:
|
57
|
-
|
58
|
-
let(:association_proxy) { Guacamole::Proxies::ReferencedBy }
|
59
|
-
let(:association_proxy_instance) { double('AssociationProxy') }
|
60
|
-
|
61
|
-
before do
|
62
|
-
allow(subject).to receive(:referenced_by_models).and_return referenced_by_models
|
63
|
-
allow(association_proxy).to receive(:new)
|
64
|
-
.with(referenced_by_model_name, model_instance)
|
65
|
-
.and_return(association_proxy_instance)
|
71
|
+
context 'with attributes as edge relations' do
|
72
|
+
let(:attribute_with_edge_relation) do
|
73
|
+
instance_double('Guacamole::DocumentModelMapper::Attribute', name: 'my_relation')
|
66
74
|
end
|
75
|
+
let(:related_edge_class) { instance_double('Guacamole::Edge') }
|
76
|
+
let(:relation_proxy_class) { Guacamole::Proxies::Relation }
|
77
|
+
let(:relation_proxy) { instance_double('Guacamole::Proxies::Relation') }
|
67
78
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
79
|
+
before do
|
80
|
+
allow(attribute_with_edge_relation).to receive(:setter).and_return('my_relation=')
|
81
|
+
allow(attribute_with_edge_relation).to receive(:edge_class).and_return(related_edge_class)
|
82
|
+
allow(subject).to receive(:edge_attributes).and_return([attribute_with_edge_relation])
|
83
|
+
allow(relation_proxy_class).to receive(:new).
|
84
|
+
with(model_instance, related_edge_class).
|
85
|
+
and_return(relation_proxy)
|
74
86
|
end
|
75
87
|
|
76
|
-
it 'should
|
77
|
-
expect(
|
88
|
+
it 'should initialize a relation proxy with the model and the appropriate edge class' do
|
89
|
+
expect(relation_proxy_class).to receive(:new).
|
90
|
+
with(model_instance, related_edge_class).
|
91
|
+
and_return(relation_proxy)
|
78
92
|
|
79
93
|
subject.document_to_model document
|
80
94
|
end
|
81
|
-
end
|
82
95
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
let(:association_proxy_instance) { double('AssociationProxy') }
|
88
|
-
|
89
|
-
before do
|
90
|
-
allow(subject).to receive(:referenced_models).and_return referenced_models
|
91
|
-
allow(association_proxy).to receive(:new)
|
92
|
-
.with(referenced_model_name, document)
|
93
|
-
.and_return(association_proxy_instance)
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'should initialize the association proxy with the document and the referenced model name' do
|
97
|
-
expect(association_proxy).to receive(:new)
|
98
|
-
.with(referenced_model_name, document)
|
99
|
-
.and_return(association_proxy_instance)
|
96
|
+
it 'should set first the key and rev and after that the proxy' do
|
97
|
+
expect(model_instance).to receive(:key=).ordered
|
98
|
+
expect(model_instance).to receive(:rev=).ordered
|
99
|
+
expect(subject).to receive(:handle_related_documents).ordered
|
100
100
|
|
101
101
|
subject.document_to_model document
|
102
102
|
end
|
103
103
|
|
104
|
-
it 'should
|
105
|
-
expect(model_instance).to receive(
|
104
|
+
it 'should assign the relation proxy for the appropriate attribute' do
|
105
|
+
expect(model_instance).to receive(:my_relation=).with(relation_proxy)
|
106
106
|
|
107
107
|
subject.document_to_model document
|
108
108
|
end
|
@@ -171,39 +171,17 @@ describe Guacamole::DocumentModelMapper do
|
|
171
171
|
end
|
172
172
|
end
|
173
173
|
|
174
|
-
context 'with
|
175
|
-
let(:
|
176
|
-
|
177
|
-
|
178
|
-
before do
|
179
|
-
allow(subject).to receive(:referenced_by_models).and_return referenced_by_models
|
174
|
+
context 'with attributes as edge relations' do
|
175
|
+
let(:attribute_with_edge_relation) do
|
176
|
+
instance_double('Guacamole::DocumentModelMapper::Attribute', name: 'my_relation')
|
180
177
|
end
|
181
178
|
|
182
|
-
it 'should remove the referenced_by attribute from the document' do
|
183
|
-
expect(model_attributes).to receive(:delete).with(referenced_by_model_name)
|
184
|
-
|
185
|
-
subject.model_to_document(model)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
context 'with referenced models' do
|
190
|
-
let(:referenced_model) { double('ReferencedModel', key: 23) }
|
191
|
-
let(:referenced_model_name) { :pony }
|
192
|
-
let(:referenced_models) { [referenced_model_name] }
|
193
|
-
|
194
179
|
before do
|
195
|
-
allow(subject).to receive(:
|
196
|
-
allow(model).to receive(:send).with(referenced_model_name).and_return referenced_model
|
180
|
+
allow(subject).to receive(:edge_attributes).and_return([attribute_with_edge_relation])
|
197
181
|
end
|
198
182
|
|
199
|
-
it 'should remove the
|
200
|
-
expect(model_attributes).to receive(:delete).with(
|
201
|
-
|
202
|
-
subject.model_to_document(model)
|
203
|
-
end
|
204
|
-
|
205
|
-
it 'should add the key of the referenced model to the document' do
|
206
|
-
expect(model_attributes).to receive(:[]=).with(:"#{referenced_model_name}_id", referenced_model.key)
|
183
|
+
it 'should remove the attributes from the document' do
|
184
|
+
expect(model_attributes).to receive(:delete).with('my_relation')
|
207
185
|
|
208
186
|
subject.model_to_document(model)
|
209
187
|
end
|
@@ -220,23 +198,52 @@ describe Guacamole::DocumentModelMapper do
|
|
220
198
|
end
|
221
199
|
end
|
222
200
|
|
223
|
-
describe '
|
224
|
-
|
201
|
+
describe 'attribute' do
|
202
|
+
describe Guacamole::DocumentModelMapper::Attribute do
|
203
|
+
subject { Guacamole::DocumentModelMapper::Attribute.new(:attribute_name) }
|
204
|
+
|
205
|
+
its(:name) { should eq :attribute_name }
|
206
|
+
its(:options) { should eq({}) }
|
207
|
+
its(:getter) { should eq :attribute_name }
|
208
|
+
its(:setter) { should eq 'attribute_name=' }
|
225
209
|
|
226
|
-
|
227
|
-
|
210
|
+
context 'attributes for relations' do
|
211
|
+
let(:edge_class) { double('SomeEdgeClass') }
|
228
212
|
|
229
|
-
|
213
|
+
before do
|
214
|
+
subject.options[:via] = edge_class
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should know if the attribute must be mapped via an edge' do
|
218
|
+
expect(subject.map_via_edge?).to be_truthy
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should hold a reference to the edge class' do
|
222
|
+
expect(subject.edge_class).to eq edge_class
|
223
|
+
end
|
224
|
+
end
|
230
225
|
end
|
231
|
-
end
|
232
226
|
|
233
|
-
describe 'references' do
|
234
227
|
subject { Guacamole::DocumentModelMapper.new FancyModel, FakeIdentityMap }
|
235
228
|
|
236
|
-
it 'should
|
237
|
-
subject.
|
229
|
+
it 'should add an attribute to be handled differently during the mapping' do
|
230
|
+
subject.attribute :special_one
|
231
|
+
|
232
|
+
expect(subject.attributes).to include Guacamole::DocumentModelMapper::Attribute.new(:special_one)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should hold a list of all attributes to be considered during the mapping' do
|
236
|
+
subject.attribute :some_attribute
|
237
|
+
subject.attribute :another_attribute
|
238
|
+
|
239
|
+
expect(subject.attributes.count).to eq 2
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should hold a list of all attributes to be mapped via Edges' do
|
243
|
+
subject.attribute :normal_attribute
|
244
|
+
subject.attribute :related_model, via: double('EdgeClass')
|
238
245
|
|
239
|
-
expect(subject.
|
246
|
+
expect(subject.edge_attributes).to include(an_object_having_attributes(name: :related_model))
|
240
247
|
end
|
241
248
|
end
|
242
249
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'guacamole/edge_collection'
|
5
|
+
|
6
|
+
describe Guacamole::EdgeCollection do
|
7
|
+
let(:graph) { double('Graph') }
|
8
|
+
let(:config) { double('Configuration') }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(Guacamole).to receive(:configuration).and_return(config)
|
12
|
+
allow(config).to receive(:graph).and_return(graph)
|
13
|
+
allow(graph).to receive(:add_edge_definition)
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'the edge collection module' do
|
17
|
+
subject { Guacamole::EdgeCollection }
|
18
|
+
|
19
|
+
context 'with user defined edge collection class' do
|
20
|
+
let(:edge_class) { double('EdgeClass', name: 'MyEdge') }
|
21
|
+
let(:user_defined_edge_collection) { double('EdgeCollection') }
|
22
|
+
|
23
|
+
before do
|
24
|
+
stub_const('MyEdgesCollection', user_defined_edge_collection)
|
25
|
+
allow(user_defined_edge_collection).to receive(:add_edge_definition_to_graph)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should return the edge collection for a given edge class' do
|
29
|
+
expect(subject.for(edge_class)).to eq user_defined_edge_collection
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'without user defined edge collection class' do
|
34
|
+
let(:edge_class) { double('EdgeClass', name: 'AmazingEdge') }
|
35
|
+
let(:auto_defined_edge_collection) { double('EdgeCollection') }
|
36
|
+
|
37
|
+
before do
|
38
|
+
stub_const('ExampleEdge', double('Edge').as_null_object)
|
39
|
+
allow(auto_defined_edge_collection).to receive(:add_edge_definition_to_graph)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should create an edge collection class' do
|
43
|
+
edge_collection = subject.create_edge_collection('ExampleEdgesCollection')
|
44
|
+
|
45
|
+
expect(edge_collection.name).to eq 'ExampleEdgesCollection'
|
46
|
+
expect(edge_collection.ancestors).to include Guacamole::EdgeCollection
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return the edge collection for a givene edge class' do
|
50
|
+
allow(subject).to receive(:create_edge_collection).
|
51
|
+
with('AmazingEdgesCollection').
|
52
|
+
and_return(auto_defined_edge_collection)
|
53
|
+
|
54
|
+
expect(subject.for(edge_class)).to eq auto_defined_edge_collection
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'concrete edge collections' do
|
60
|
+
subject do
|
61
|
+
class SomeEdgesCollection
|
62
|
+
include Guacamole::EdgeCollection
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:database) { double('Database') }
|
67
|
+
let(:edge_collection_name) { 'some_edges' }
|
68
|
+
let(:raw_edge_collection) { double('Ashikawa::Core::EdgeCollection') }
|
69
|
+
let(:collection_a) { :a }
|
70
|
+
let(:collection_b) { :b }
|
71
|
+
let(:edge_class) { double('EdgeClass', name: 'SomeEdge', from: collection_a, to: collection_b) }
|
72
|
+
let(:model) { double('Model') }
|
73
|
+
|
74
|
+
before do
|
75
|
+
stub_const('SomeEdge', edge_class)
|
76
|
+
allow(graph).to receive(:edge_collection).with(edge_collection_name).and_return(raw_edge_collection)
|
77
|
+
allow(subject).to receive(:database).and_return(database)
|
78
|
+
allow(graph).to receive(:add_edge_definition)
|
79
|
+
end
|
80
|
+
|
81
|
+
after do
|
82
|
+
# This stunt is required to have a fresh subject each time and not running into problems
|
83
|
+
# with cached mock doubles that will raise errors upon test execution.
|
84
|
+
Object.send(:remove_const, subject.name)
|
85
|
+
end
|
86
|
+
|
87
|
+
its(:edge_class) { should eq edge_class }
|
88
|
+
|
89
|
+
it 'should be a specialized Guacamole::Collection' do
|
90
|
+
expect(subject).to include Guacamole::Collection
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should map the #connectino to the underlying edge_connection' do
|
94
|
+
allow(subject).to receive(:graph).and_return(graph)
|
95
|
+
|
96
|
+
expect(subject.connection).to eq raw_edge_collection
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'initialize the edge definition' do
|
100
|
+
it 'should add the edge definition as soon as the module is included' do
|
101
|
+
just_another_edge_collection = Class.new
|
102
|
+
expect(just_another_edge_collection).to receive(:add_edge_definition_to_graph)
|
103
|
+
|
104
|
+
just_another_edge_collection.send(:include, Guacamole::EdgeCollection)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should ignore if the the edge definition was already added' do
|
108
|
+
expect(graph).to receive(:add_edge_definition).and_raise(Ashikawa::Core::ResourceNotFound)
|
109
|
+
|
110
|
+
expect { subject.add_edge_definition_to_graph }.not_to raise_error
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should create the edge definition based on the edge class' do
|
114
|
+
expect(graph).to receive(:add_edge_definition).with(edge_collection_name,
|
115
|
+
from: [collection_a], to: [collection_b])
|
116
|
+
|
117
|
+
subject.add_edge_definition_to_graph
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'accessing the mapper' do
|
122
|
+
let(:collection_a) { double('Collection') }
|
123
|
+
let(:collection_b) { double('Collection') }
|
124
|
+
let(:mapper_a) { double('DocumentModelMapper') }
|
125
|
+
let(:mapper_b) { double('DocumentModelMapper') }
|
126
|
+
|
127
|
+
before do
|
128
|
+
allow(collection_a).to receive(:mapper).and_return(mapper_a)
|
129
|
+
allow(collection_b).to receive(:mapper).and_return(mapper_b)
|
130
|
+
allow(edge_class).to receive(:from_collection).and_return(collection_a)
|
131
|
+
allow(edge_class).to receive(:to_collection).and_return(collection_b)
|
132
|
+
allow(mapper_a).to receive(:responsible_for?).with(model).and_return(true)
|
133
|
+
allow(mapper_b).to receive(:responsible_for?).with(model).and_return(false)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should provide a method to get the mapper for the :to collection' do
|
137
|
+
expect(subject.mapper_for_target(model)).to eq mapper_b
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should provide a method to get the mapper for the :from collection' do
|
141
|
+
expect(subject.mapper_for_start(model)).to eq mapper_a
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'getting neighbors' do
|
146
|
+
let(:graph_query) { instance_double('Guacamole::GraphQuery') }
|
147
|
+
let(:target_mapper) { double('DocumentModelMapper') }
|
148
|
+
|
149
|
+
before do
|
150
|
+
allow(Guacamole::GraphQuery).to receive(:new).and_return(graph_query)
|
151
|
+
allow(subject).to receive(:mapper_for_target).with(model).and_return(target_mapper)
|
152
|
+
allow(graph_query).to receive(:neighbors).and_return(graph_query)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should return a query object' do
|
156
|
+
query = subject.neighbors(model)
|
157
|
+
|
158
|
+
expect(query).to eq graph_query
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should initialize the query object with the graph an the appropriate mapper' do
|
162
|
+
expect(Guacamole::GraphQuery).to receive(:new).with(graph, target_mapper).and_return(graph_query)
|
163
|
+
|
164
|
+
subject.neighbors(model)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should provide a #neighbors function' do
|
168
|
+
expect(graph_query).to receive(:neighbors).with(model, 'some_edges')
|
169
|
+
|
170
|
+
subject.neighbors(model)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|