ashikawa-core 0.1 → 0.2
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/Guardfile +18 -0
- data/README.md +10 -10
- data/Rakefile +5 -4
- data/ashikawa-core.gemspec +14 -6
- data/lib/ashikawa-core.rb +1 -0
- data/lib/ashikawa-core/collection.rb +189 -98
- data/lib/ashikawa-core/connection.rb +18 -20
- data/lib/ashikawa-core/cursor.rb +65 -0
- data/lib/ashikawa-core/database.rb +33 -46
- data/lib/ashikawa-core/document.rb +63 -22
- data/lib/ashikawa-core/exceptions/document_not_found.rb +8 -0
- data/lib/ashikawa-core/index.rb +47 -0
- data/lib/ashikawa-core/version.rb +1 -1
- data/spec/fixtures/cursor/26011191-2.json +19 -0
- data/spec/fixtures/cursor/26011191-3.json +13 -0
- data/spec/fixtures/cursor/26011191.json +19 -0
- data/spec/fixtures/cursor/query.json +18 -0
- data/spec/fixtures/documents/new-4590-333.json +5 -0
- data/spec/fixtures/indices/all.json +22 -0
- data/spec/fixtures/indices/hash-index.json +12 -0
- data/spec/fixtures/indices/new-hash-index.json +12 -0
- data/spec/fixtures/simple-queries/all.json +10 -4
- data/spec/fixtures/simple-queries/all_limit.json +9 -3
- data/spec/fixtures/simple-queries/all_skip.json +9 -3
- data/spec/fixtures/simple-queries/example.json +9 -3
- data/spec/fixtures/simple-queries/near.json +11 -5
- data/spec/fixtures/simple-queries/range.json +10 -0
- data/spec/fixtures/simple-queries/within.json +9 -3
- data/spec/integration/arango_helper.rb +27 -0
- data/spec/integration/basic_spec.rb +107 -28
- data/spec/integration/spec_helper.rb +0 -28
- data/spec/unit/collection_spec.rb +190 -83
- data/spec/unit/connection_spec.rb +17 -17
- data/spec/unit/cursor_spec.rb +75 -0
- data/spec/unit/database_spec.rb +34 -19
- data/spec/unit/document_spec.rb +77 -6
- data/spec/unit/index_spec.rb +39 -0
- metadata +98 -6
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"hasMore": true,
|
3
|
+
"error": false,
|
4
|
+
"id": 26011191,
|
5
|
+
"result": [
|
6
|
+
{
|
7
|
+
"n": 0,
|
8
|
+
"_rev": 25880119,
|
9
|
+
"_id": "23914039/25880119"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"n": 1,
|
13
|
+
"_rev": 25880119,
|
14
|
+
"_id": "23914039/25880119"
|
15
|
+
}
|
16
|
+
],
|
17
|
+
"code": 201,
|
18
|
+
"count": 5
|
19
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"code": 200,
|
3
|
+
"indexes": [
|
4
|
+
{
|
5
|
+
"fields": [
|
6
|
+
"_id"
|
7
|
+
],
|
8
|
+
"id": "4590/0",
|
9
|
+
"type": "primary"
|
10
|
+
}
|
11
|
+
],
|
12
|
+
"error": false,
|
13
|
+
"identifiers": {
|
14
|
+
"176836793/0": {
|
15
|
+
"fields": [
|
16
|
+
"_id"
|
17
|
+
],
|
18
|
+
"id": "4590/0",
|
19
|
+
"type": "primary"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
@@ -1,4 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
{
|
2
|
+
"code": 201,
|
3
|
+
"hasMore": false,
|
4
|
+
"count": 1,
|
5
|
+
"error": false,
|
6
|
+
"result": [
|
7
|
+
{ "_id" : "12345/57463", "_rev" : 57463, "hello" : "world" },
|
8
|
+
{ "_id" : "12346/3872", "_rev" : 3872, "key" : "value" }
|
9
|
+
]
|
10
|
+
}
|
@@ -1,5 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
{
|
2
|
+
"code": 201,
|
3
|
+
"hasMore": false,
|
4
|
+
"count": 3,
|
5
|
+
"error": false,
|
6
|
+
"result": [
|
7
|
+
{ "_id" : "12345/57463", "_rev" : 57463, "name" : "world/0/0", "loc" : [0, 0] },
|
8
|
+
{ "_id" : "12346/2938", "_rev" : 2938, "name" : "world/0/10", "loc" : [0, 10] },
|
9
|
+
{ "_id" : "12347/23737", "_rev" : 23737, "name" : "world/-10/0", "loc" : [-10, 0] }
|
10
|
+
]
|
11
|
+
}
|
@@ -1,3 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
{
|
2
|
+
"code": 201,
|
3
|
+
"hasMore": false,
|
4
|
+
"count": 1,
|
5
|
+
"error": false,
|
6
|
+
"result": [
|
7
|
+
{ "_id" : "12345/57463", "_rev" : 57463, "name" : "world/0/0", "loc" : [0, 0] }
|
8
|
+
]
|
9
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
raise "Could not find arangod. Please install it or check if it is in your path." if `which arangod` == ""
|
3
|
+
|
4
|
+
database_directory = "/tmp/ashikawa-integration"
|
5
|
+
arango_process = false
|
6
|
+
|
7
|
+
config.before(:suite) do
|
8
|
+
puts "Starting ArangoDB"
|
9
|
+
process_id = $$
|
10
|
+
|
11
|
+
Dir.mkdir database_directory unless Dir.exists? database_directory
|
12
|
+
arango_process = IO.popen("arangod #{database_directory} --watch-process #{process_id}")
|
13
|
+
|
14
|
+
sleep 2 # Wait for Arango to start up
|
15
|
+
end
|
16
|
+
|
17
|
+
config.after(:suite) do
|
18
|
+
puts
|
19
|
+
puts "Shutting down ArangoDB"
|
20
|
+
|
21
|
+
Process.kill "INT", arango_process.pid
|
22
|
+
sleep 2 # Wait for Arango to shut down
|
23
|
+
arango_process.close
|
24
|
+
|
25
|
+
`rm -r #{database_directory}/*`
|
26
|
+
end
|
27
|
+
end
|
@@ -1,14 +1,20 @@
|
|
1
1
|
require 'integration/spec_helper'
|
2
2
|
|
3
|
+
ARANGO_HOST = "http://localhost:8529"
|
4
|
+
|
3
5
|
describe "Basics" do
|
4
|
-
subject {
|
6
|
+
subject { ARANGO_HOST }
|
5
7
|
|
6
8
|
it "should have booted up an ArangoDB instance" do
|
7
|
-
expect {
|
9
|
+
expect { RestClient.get(subject) }.to_not raise_error
|
8
10
|
end
|
9
11
|
|
10
12
|
describe "initialized database" do
|
11
|
-
subject { Ashikawa::Core::Database.new
|
13
|
+
subject { Ashikawa::Core::Database.new ARANGO_HOST }
|
14
|
+
|
15
|
+
after :each do
|
16
|
+
subject.collections.each { |collection| collection.delete }
|
17
|
+
end
|
12
18
|
|
13
19
|
it "should do what the README describes" do
|
14
20
|
subject["my_collection"]
|
@@ -33,12 +39,12 @@ describe "Basics" do
|
|
33
39
|
my_collection.name.should == "my_new_name"
|
34
40
|
end
|
35
41
|
|
36
|
-
it "should be possible to find a collection by ID" do
|
42
|
+
it "should be possible to find a collection by ID" do
|
37
43
|
my_collection = subject["test_collection"]
|
38
44
|
subject[my_collection.id].name.should == "test_collection"
|
39
45
|
end
|
40
46
|
|
41
|
-
it "should be possible to load and unload collections" do
|
47
|
+
it "should be possible to load and unload collections" do
|
42
48
|
my_collection = subject["test_collection"]
|
43
49
|
my_collection.loaded?.should be_true
|
44
50
|
my_collection.unload
|
@@ -47,7 +53,7 @@ describe "Basics" do
|
|
47
53
|
subject[my_id].loaded?.should be_false
|
48
54
|
end
|
49
55
|
|
50
|
-
it "should be possible to get figures" do
|
56
|
+
it "should be possible to get figures" do
|
51
57
|
my_collection = subject["test_collection"]
|
52
58
|
my_collection.figure(:datafiles_count).class.should == Fixnum
|
53
59
|
my_collection.figure(:alive_size).class.should == Fixnum
|
@@ -58,13 +64,13 @@ describe "Basics" do
|
|
58
64
|
|
59
65
|
it "should change and receive information about waiting for sync" do
|
60
66
|
my_collection = subject["my_collection"]
|
67
|
+
my_collection.wait_for_sync = false
|
61
68
|
my_collection.wait_for_sync?.should be_false
|
62
69
|
my_collection.wait_for_sync = true
|
63
70
|
my_collection.wait_for_sync?.should be_true
|
64
71
|
end
|
65
72
|
|
66
73
|
it "should be possible to get information about the number of documents" do
|
67
|
-
pending("`<<` not implemented yet")
|
68
74
|
empty_collection = subject["empty_collection"]
|
69
75
|
empty_collection.length.should == 0
|
70
76
|
empty_collection << { name: "testname", age: 27}
|
@@ -75,14 +81,12 @@ describe "Basics" do
|
|
75
81
|
end
|
76
82
|
|
77
83
|
it "should return all documents of a collection" do
|
78
|
-
pending("`<<` not implemented yet")
|
79
84
|
empty_collection = subject["empty_collection"]
|
80
85
|
empty_collection << { name: "testname", age: 27}
|
81
86
|
empty_collection.all.first["name"].should == "testname"
|
82
87
|
end
|
83
88
|
|
84
89
|
it "should be possible to limit and skip results" do
|
85
|
-
pending("`<<` not implemented yet")
|
86
90
|
empty_collection = subject["empty_collection"]
|
87
91
|
empty_collection.truncate!
|
88
92
|
|
@@ -94,11 +98,20 @@ describe "Basics" do
|
|
94
98
|
empty_collection.all(skip: 2).length.should == 1
|
95
99
|
end
|
96
100
|
|
101
|
+
it "should be possible to update the attributes of a document" do
|
102
|
+
collection = subject["documenttests"]
|
103
|
+
|
104
|
+
document = collection.create name: "The Dude", bowling: true
|
105
|
+
document_id = document.id
|
106
|
+
document["name"] = "Other Dude"
|
107
|
+
document.save
|
108
|
+
|
109
|
+
collection[document_id]["name"].should == "Other Dude"
|
110
|
+
end
|
97
111
|
|
98
112
|
it "should be possible to access and create documents from a collection" do
|
99
113
|
collection = subject["documenttests"]
|
100
114
|
|
101
|
-
pending("`create` not implemented yet")
|
102
115
|
document = collection.create name: "The Dude", bowling: true
|
103
116
|
document_id = document.id
|
104
117
|
collection[document_id]["name"].should == "The Dude"
|
@@ -112,37 +125,53 @@ describe "Basics" do
|
|
112
125
|
@places = subject['geo_collection']
|
113
126
|
@places.truncate!
|
114
127
|
|
115
|
-
|
116
|
-
@places << { name
|
117
|
-
@places << { name
|
128
|
+
@places.add_index :geo, on: [:latitude, :longitude]
|
129
|
+
@places << { "name" => "cologne", "latitude" => 50.948045, "longitude" => 6.961212 }
|
130
|
+
@places << { "name" => "san francisco", "latitude" => -122.395899, "longitude" => 37.793621 }
|
118
131
|
end
|
119
132
|
|
120
133
|
it "should be possible to query documents near a certain location" do
|
121
|
-
|
122
|
-
|
123
|
-
near_places.first.name.should == "san francisco"
|
134
|
+
found_places = @places.near latitude: 50, longitude: 6
|
135
|
+
found_places.first["name"].should == "cologne"
|
124
136
|
end
|
125
137
|
|
126
138
|
it "should be possible to query documents within a certain range" do
|
127
|
-
|
128
|
-
|
129
|
-
|
139
|
+
found_places = @places.within latitude: 50.948040, longitude: 6.961210, radius: 2
|
140
|
+
found_places.length.should == 1
|
141
|
+
found_places.first["name"].should == "cologne"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "ranges" do
|
146
|
+
before :each do
|
147
|
+
@people = subject['range_collection']
|
148
|
+
@people.truncate!
|
149
|
+
|
150
|
+
@people.add_index :skiplist, on: [:age]
|
151
|
+
@people << { "name" => "Georg", "age" => 12 }
|
152
|
+
@people << { "name" => "Anne", "age" => 21 }
|
153
|
+
@people << { "name" => "Jens", "age" => 49 }
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should be possible to query documents for numbers in a certain range" do
|
157
|
+
found_people = @people.in_range attribute: "age", left: 20, right: 30, closed: true
|
158
|
+
found_people.length.should == 1
|
159
|
+
found_people.first["name"].should == "Anne"
|
130
160
|
end
|
131
161
|
end
|
132
162
|
|
133
163
|
describe "created document" do
|
134
164
|
before :each do
|
135
|
-
pending("`create` not implemented yet")
|
136
165
|
@collection = subject["documenttests"]
|
137
166
|
@document = @collection.create name: "The Dude"
|
138
167
|
@document_id = @document.id
|
139
168
|
end
|
140
169
|
|
141
170
|
it "should be possible to manipulate documents and save them" do
|
142
|
-
@document = @collection[document_id]
|
171
|
+
@document = @collection[@document_id]
|
143
172
|
@document["name"] = "Jeffrey Lebowski"
|
144
173
|
@document["name"].should == "Jeffrey Lebowski"
|
145
|
-
@collection[@document_id].should == "The Dude"
|
174
|
+
@collection[@document_id]["name"].should == "The Dude"
|
146
175
|
@document.save
|
147
176
|
@collection[@document_id]["name"].should == "Jeffrey Lebowski"
|
148
177
|
end
|
@@ -152,16 +181,66 @@ describe "Basics" do
|
|
152
181
|
@document = @collection.create name: "The Dude"
|
153
182
|
@document_id = @document.id
|
154
183
|
@collection[@document_id].delete
|
155
|
-
expect { @collection[@document_id] }.to raise_exception Ashikawa::DocumentNotFoundException
|
184
|
+
expect { @collection[@document_id] }.to raise_exception Ashikawa::Core::DocumentNotFoundException
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should not be possible to delete a document that doesn't exist" do
|
188
|
+
@collection = subject["documenttests"]
|
189
|
+
expect { @collection[123].delete }.to raise_exception Ashikawa::Core::DocumentNotFoundException
|
156
190
|
end
|
157
191
|
end
|
158
192
|
|
159
|
-
|
160
|
-
|
193
|
+
describe "setting and deleting indices" do
|
194
|
+
before :each do
|
195
|
+
@collection = subject["documenttests"]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should be possible to set indices" do
|
199
|
+
@collection.add_index :geo, on: [:latitude, :longitude]
|
200
|
+
@collection.add_index :skiplist, on: [:identifier]
|
201
|
+
@collection.indices.length.should == 3 # primary index is always set
|
202
|
+
@collection.indices[0].class.should == Ashikawa::Core::Index
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should be possible to get an index by ID" do
|
206
|
+
index = @collection.add_index :skiplist, on: [:identifier]
|
207
|
+
@collection.index(index.id).id.should == index.id
|
208
|
+
end
|
161
209
|
|
162
|
-
|
163
|
-
|
164
|
-
|
210
|
+
it "should be possible to remove indices" do
|
211
|
+
index = @collection.add_index :skiplist, on: [:identifier]
|
212
|
+
index.delete
|
213
|
+
@collection.indices.length.should == 1 # primary index is always set
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "querying for documents" do
|
218
|
+
it "should be possible to query documents by example" do
|
219
|
+
collection = subject["documenttests"]
|
220
|
+
|
221
|
+
collection << { "name" => "Random Collection" }
|
222
|
+
result = collection.by_example example: {"name" => "Random Collection"}
|
223
|
+
result.length.should == 1
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should be possible to query documents with AQL" do
|
227
|
+
collection = subject["aqltest"]
|
228
|
+
|
229
|
+
collection << { "name" => "Jeff Lebowski", "bowling" => true }
|
230
|
+
collection << { "name" => "Walter Sobchak", "bowling" => true }
|
231
|
+
collection << { "name" => "Donny Kerabatsos", "bowling" => true }
|
232
|
+
collection << { "name" => "Jeffrey Lebowski", "bowling" => false }
|
233
|
+
|
234
|
+
results = subject.query "FOR u IN aqltest FILTER u.bowling == true RETURN u",
|
235
|
+
batch_size: 2,
|
236
|
+
count: true
|
237
|
+
|
238
|
+
results.length.should == 3
|
239
|
+
|
240
|
+
results = results.map { |person| person["name"] }
|
241
|
+
results.should include "Jeff Lebowski"
|
242
|
+
results.should_not include "Jeffrey Lebowski"
|
243
|
+
end
|
165
244
|
end
|
166
245
|
end
|
167
246
|
end
|