ashikawa-core 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/Guardfile +18 -0
  2. data/README.md +10 -10
  3. data/Rakefile +5 -4
  4. data/ashikawa-core.gemspec +14 -6
  5. data/lib/ashikawa-core.rb +1 -0
  6. data/lib/ashikawa-core/collection.rb +189 -98
  7. data/lib/ashikawa-core/connection.rb +18 -20
  8. data/lib/ashikawa-core/cursor.rb +65 -0
  9. data/lib/ashikawa-core/database.rb +33 -46
  10. data/lib/ashikawa-core/document.rb +63 -22
  11. data/lib/ashikawa-core/exceptions/document_not_found.rb +8 -0
  12. data/lib/ashikawa-core/index.rb +47 -0
  13. data/lib/ashikawa-core/version.rb +1 -1
  14. data/spec/fixtures/cursor/26011191-2.json +19 -0
  15. data/spec/fixtures/cursor/26011191-3.json +13 -0
  16. data/spec/fixtures/cursor/26011191.json +19 -0
  17. data/spec/fixtures/cursor/query.json +18 -0
  18. data/spec/fixtures/documents/new-4590-333.json +5 -0
  19. data/spec/fixtures/indices/all.json +22 -0
  20. data/spec/fixtures/indices/hash-index.json +12 -0
  21. data/spec/fixtures/indices/new-hash-index.json +12 -0
  22. data/spec/fixtures/simple-queries/all.json +10 -4
  23. data/spec/fixtures/simple-queries/all_limit.json +9 -3
  24. data/spec/fixtures/simple-queries/all_skip.json +9 -3
  25. data/spec/fixtures/simple-queries/example.json +9 -3
  26. data/spec/fixtures/simple-queries/near.json +11 -5
  27. data/spec/fixtures/simple-queries/range.json +10 -0
  28. data/spec/fixtures/simple-queries/within.json +9 -3
  29. data/spec/integration/arango_helper.rb +27 -0
  30. data/spec/integration/basic_spec.rb +107 -28
  31. data/spec/integration/spec_helper.rb +0 -28
  32. data/spec/unit/collection_spec.rb +190 -83
  33. data/spec/unit/connection_spec.rb +17 -17
  34. data/spec/unit/cursor_spec.rb +75 -0
  35. data/spec/unit/database_spec.rb +34 -19
  36. data/spec/unit/document_spec.rb +77 -6
  37. data/spec/unit/index_spec.rb +39 -0
  38. metadata +98 -6
@@ -4,31 +4,3 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
4
4
  require "rest-client"
5
5
  require "json"
6
6
  require "ashikawa-core"
7
-
8
- RSpec.configure do |config|
9
- raise "Could not find arangod. Please install it or check if it is in your path." if `which arangod` == ""
10
-
11
- database_directory = "/tmp/ashikawa-integration"
12
- arango_process = false
13
-
14
- config.before(:suite) do
15
- puts "Starting ArangoDB"
16
- process_id = $$
17
-
18
- Dir.mkdir database_directory unless Dir.exists? database_directory
19
- arango_process = IO.popen("arangod #{database_directory} --watch-process #{process_id}")
20
-
21
- sleep 2 # Wait for Arango to start up
22
- end
23
-
24
- config.after(:suite) do
25
- puts
26
- puts "Shutting down ArangoDB"
27
-
28
- Process.kill "INT", arango_process.pid
29
- sleep 2 # Wait for Arango to shut down
30
- arango_process.close
31
-
32
- `rm -r #{database_directory}/*`
33
- end
34
- end
@@ -3,200 +3,298 @@ require 'ashikawa-core/collection'
3
3
 
4
4
  describe Ashikawa::Core::Collection do
5
5
  subject { Ashikawa::Core::Collection }
6
-
6
+
7
7
  before :each do
8
8
  @database = double()
9
+ mock { Ashikawa::Core::Cursor }
9
10
  end
10
-
11
+
11
12
  it "should have a name" do
12
13
  my_collection = subject.new @database, server_response("/collections/4588")
13
14
  my_collection.name.should == "example_1"
14
15
  end
15
-
16
+
16
17
  it "should accept an ID" do
17
18
  my_collection = subject.new @database, server_response("/collections/4588")
18
19
  my_collection.id.should == 4588
19
20
  end
20
-
21
+
21
22
  describe "the status code" do
22
23
  it "should know if the collection is new born" do
23
24
  my_collection = subject.new @database, { "status" => "1" }
24
25
  my_collection.new_born?.should == true
25
-
26
+
26
27
  my_collection = subject.new @database, { "status" => "200" }
27
28
  my_collection.new_born?.should == false
28
29
  end
29
-
30
+
30
31
  it "should know if the collection is unloaded" do
31
32
  my_collection = subject.new @database, { "status" => "2" }
32
33
  my_collection.unloaded?.should == true
33
-
34
+
34
35
  my_collection = subject.new @database, { "status" => "200" }
35
36
  my_collection.unloaded?.should == false
36
37
  end
37
-
38
+
38
39
  it "should know if the collection is loaded" do
39
40
  my_collection = subject.new @database, { "status" => "3" }
40
41
  my_collection.loaded?.should == true
41
-
42
+
42
43
  my_collection = subject.new @database, { "status" => "200" }
43
44
  my_collection.loaded?.should == false
44
45
  end
45
-
46
+
46
47
  it "should know if the collection is being unloaded" do
47
48
  my_collection = subject.new @database, { "status" => "4" }
48
49
  my_collection.being_unloaded?.should == true
49
-
50
+
50
51
  my_collection = subject.new @database, { "status" => "200" }
51
52
  my_collection.being_unloaded?.should == false
52
53
  end
53
-
54
+
54
55
  it "should know if the collection is corrupted" do
55
56
  my_collection = subject.new @database, { "status" => "6" }
56
57
  my_collection.corrupted?.should == true
57
58
  end
58
59
  end
59
-
60
+
60
61
  describe "attributes of a collection" do
61
62
  it "should check if the collection waits for sync" do
62
- @database.stub(:send_request).with("/collection/4590/properties").and_return { server_response("/collections/4590") }
63
- @database.should_receive(:send_request).with("/collection/4590/properties")
64
-
63
+ @database.stub(:send_request).with("/collection/4590/properties", {}).and_return { server_response("/collections/4590") }
64
+ @database.should_receive(:send_request).with("/collection/4590/properties", {})
65
+
65
66
  my_collection = subject.new @database, { "id" => "4590" }
66
67
  my_collection.wait_for_sync?.should be_true
67
68
  end
68
-
69
+
69
70
  it "should know how many documents the collection has" do
70
- @database.stub(:send_request).with("/collection/4590/count").and_return { server_response("/collections/4590-properties") }
71
- @database.should_receive(:send_request).with("/collection/4590/count")
72
-
71
+ @database.stub(:send_request).with("/collection/4590/count", {}).and_return { server_response("/collections/4590-properties") }
72
+ @database.should_receive(:send_request).with("/collection/4590/count", {})
73
+
73
74
  my_collection = subject.new @database, { "id" => "4590" }
74
75
  my_collection.length.should == 54
75
76
  end
76
-
77
+
77
78
  it "should check for the figures" do
78
- @database.stub(:send_request).with("/collection/73482/figures").and_return { server_response("/collections/73482-figures") }
79
- @database.should_receive(:send_request).with("/collection/73482/figures")
80
-
79
+ @database.stub(:send_request).with("/collection/73482/figures", {}).and_return { server_response("/collections/73482-figures") }
80
+ @database.should_receive(:send_request).with("/collection/73482/figures", {}).at_least(1).times
81
+
81
82
  my_collection = subject.new @database, { "id" => "73482" }
82
83
  my_collection.figure(:datafiles_count).should == 1
83
- my_collection.figure(:alive_size).should == 0
84
- my_collection.figure(:alive_count).should == 0
85
- my_collection.figure(:dead_size).should == 2384
86
- my_collection.figure(:dead_count).should == 149
84
+ my_collection.figure(:alive_size).should == 0
85
+ my_collection.figure(:alive_count).should == 0
86
+ my_collection.figure(:dead_size).should == 2384
87
+ my_collection.figure(:dead_count).should == 149
87
88
  end
88
89
  end
89
-
90
+
90
91
  describe "an initialized collection" do
91
92
  subject { Ashikawa::Core::Collection.new @database, { "id" => "4590", "name" => "example_1" } }
92
-
93
+
93
94
  it "should get deleted" do
94
95
  @database.stub(:send_request).with("/collection/4590", delete: {})
95
96
  @database.should_receive(:send_request).with("/collection/4590", delete: {})
96
-
97
+
97
98
  subject.delete
98
99
  end
99
-
100
+
100
101
  it "should get loaded" do
101
102
  @database.stub(:send_request).with("/collection/4590/load", put: {})
102
103
  @database.should_receive(:send_request).with("/collection/4590/load", put: {})
103
-
104
+
104
105
  subject.load
105
106
  end
106
-
107
+
107
108
  it "should get unloaded" do
108
109
  @database.stub(:send_request).with("/collection/4590/unload", put: {})
109
110
  @database.should_receive(:send_request).with("/collection/4590/unload", put: {})
110
-
111
+
111
112
  subject.unload
112
113
  end
113
-
114
+
114
115
  it "should get truncated" do
115
116
  @database.stub(:send_request).with("/collection/4590/truncate", put: {})
116
117
  @database.should_receive(:send_request).with("/collection/4590/truncate", put: {})
117
-
118
+
118
119
  subject.truncate!
119
120
  end
120
-
121
+
121
122
  it "should change if it waits for sync" do
122
123
  @database.stub(:send_request).with("/collection/4590/properties", put: {"waitForSync" => true})
123
124
  @database.should_receive(:send_request).with("/collection/4590/properties", put: {"waitForSync" => true})
124
-
125
+
125
126
  subject.wait_for_sync = true
126
127
  end
127
-
128
+
128
129
  it "should change its name" do
129
130
  @database.stub(:send_request).with("/collection/4590/rename", put: {"name" => "my_new_name"})
130
131
  @database.should_receive(:send_request).with("/collection/4590/rename", put: {"name" => "my_new_name"})
131
-
132
+
132
133
  subject.name = "my_new_name"
133
134
  end
134
-
135
+
135
136
  describe "working with documents" do
136
-
137
+
138
+ describe "add and get single documents" do
139
+ it "should receive a document by ID" do
140
+ @database.stub(:send_request).with("/document/4590/333").and_return { server_response('documents/4590-333') }
141
+ @database.should_receive(:send_request).with("/document/4590/333")
142
+
143
+ # Documents need to get initialized:
144
+ Ashikawa::Core::Document.should_receive(:new)
145
+
146
+ subject[333]
147
+ end
148
+
149
+ it "should replace a document by ID" do
150
+ @database.stub(:send_request).with("/document/4590/333", put: {"name" => "The Dude"})
151
+ @database.should_receive(:send_request).with("/document/4590/333", put: {"name" => "The Dude"})
152
+
153
+ subject[333] = {"name" => "The Dude"}
154
+ end
155
+
156
+ it "should create a new document" do
157
+ @database.stub(:send_request).with("/document?collection=4590", post: { "name" => "The Dude" }).and_return do
158
+ server_response('documents/new-4590-333')
159
+ end
160
+ @database.stub(:send_request).with("/document/4590/333", post: { "name" => "The Dude" }).and_return { server_response('documents/4590-333') }
161
+
162
+ # Documents need to get initialized:
163
+ Ashikawa::Core::Document.should_receive(:new)
164
+
165
+ subject.create({"name" => "The Dude"})
166
+ end
167
+
168
+ it "should create a new document with `<<`" do
169
+ @database.stub(:send_request).with("/document?collection=4590", post: { "name" => "The Dude" }).and_return do
170
+ server_response('documents/new-4590-333')
171
+ end
172
+ @database.stub(:send_request).with("/document/4590/333").and_return { server_response('documents/4590-333') }
173
+
174
+ # Documents need to get initialized:
175
+ Ashikawa::Core::Document.should_receive(:new)
176
+
177
+ subject << {"name" => "The Dude"}
178
+ end
179
+ end
180
+
137
181
  describe "list all" do
138
182
  it "should list all documents" do
139
183
  @database.stub(:send_request).with("/simple/all", put: {"collection" => "example_1"}).and_return { server_response('simple-queries/all') }
140
184
  @database.should_receive(:send_request).with("/simple/all", put: {"collection" => "example_1"})
141
-
185
+
142
186
  # Documents need to get initialized:
143
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
144
- Ashikawa::Core::Document.should_receive(:new).with("12346/3872", 3872)
145
-
187
+ Ashikawa::Core::Cursor.should_receive(:new)
188
+
146
189
  subject.all
147
190
  end
148
-
191
+
149
192
  it "should limit to a certain amount" do
150
193
  @database.stub(:send_request).with("/simple/all", put: {"collection" => "example_1", "limit" => 1}).and_return { server_response('simple-queries/all_skip') }
151
194
  @database.should_receive(:send_request).with("/simple/all", put: {"collection" => "example_1", "limit" => 1})
152
-
153
- Ashikawa::Core::Document.should_receive(:new).with("12346/3872", 3872)
154
-
195
+
196
+ Ashikawa::Core::Cursor.should_receive(:new)
197
+
155
198
  subject.all :limit => 1
156
199
  end
157
-
200
+
158
201
  it "should skip documents" do
159
202
  @database.stub(:send_request).with("/simple/all", put: {"collection" => "example_1", "skip" => 1}).and_return { server_response('simple-queries/all_limit') }
160
203
  @database.should_receive(:send_request).with("/simple/all", put: {"collection" => "example_1", "skip" => 1})
161
-
162
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
163
-
204
+
205
+ Ashikawa::Core::Cursor.should_receive(:new)
206
+
164
207
  subject.all :skip => 1
165
208
  end
166
209
  end
167
-
210
+
211
+ describe "indices" do
212
+ it "should add a new index" do
213
+ @database.stub(:send_request).with("/index?collection=4590", post: {
214
+ "type" => "hash", "fields" => [ "a", "b" ]
215
+ }).and_return { server_response('indices/new-hash-index') }
216
+ @database.should_receive(:send_request).with("/index?collection=4590", post: {
217
+ "type" => "hash", "fields" => [ "a", "b" ]
218
+ })
219
+
220
+ Ashikawa::Core::Index.should_receive(:new).with(subject,
221
+ server_response('indices/new-hash-index'))
222
+
223
+ subject.add_index :hash, on: [ :a, :b ]
224
+ end
225
+
226
+ it "should get an index by ID" do
227
+ @database.stub(:send_request).with(
228
+ "/index/4590/168054969"
229
+ ).and_return { server_response('indices/hash-index') }
230
+
231
+ Ashikawa::Core::Index.should_receive(:new).with(subject,
232
+ server_response('indices/hash-index'))
233
+
234
+ subject.index 168054969
235
+ end
236
+
237
+ it "should get all indices" do
238
+ @database.stub(:send_request).with(
239
+ "/index?collection=4590"
240
+ ).and_return { server_response('indices/all') }
241
+
242
+ Ashikawa::Core::Index.should_receive(:new).exactly(1).times
243
+
244
+ indices = subject.indices
245
+ indices.length.should == 1
246
+ end
247
+ end
248
+
168
249
  describe "by example" do
169
250
  before(:each) do
170
- @search_params = { :hello => "world" }
251
+ @example = { :hello => "world" }
171
252
  end
172
-
253
+
173
254
  it "should find documents by example" do
174
- @database.stub(:send_request).with("/simple/by-example", put: {"collection" => "example_1", "example" => { :hello => "world"}}).and_return { server_response('simple-queries/example') }
175
- @database.should_receive(:send_request).with("/simple/by-example", put: {"collection" => "example_1", "example" => { :hello => "world"}})
176
-
177
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
178
-
179
- subject.by_example(@search_params)
180
- end
181
-
255
+ @database.stub(:send_request).with("/simple/by-example", put:
256
+ {"collection" => "example_1", "example" => { :hello => "world"}}
257
+ ).and_return { server_response('simple-queries/example') }
258
+ @database.should_receive(:send_request).with("/simple/by-example", put:
259
+ {"collection" => "example_1", "example" => { :hello => "world"}})
260
+
261
+ Ashikawa::Core::Cursor.should_receive(:new)
262
+
263
+ subject.by_example example: @example
264
+ end
265
+
266
+ it "should find one document by example" do
267
+ @database.stub(:send_request).with("/simple/first-example", put:
268
+ {"collection" => "example_1", "example" => { :hello => "world"}}
269
+ ).and_return { server_response('simple-queries/example') }
270
+ @database.should_receive(:send_request).with("/simple/first-example", put:
271
+ {"collection" => "example_1", "example" => { :hello => "world"}})
272
+
273
+ Ashikawa::Core::Document.should_receive(:new)
274
+
275
+ subject.first_example @example
276
+ end
277
+
182
278
  it "should skip documents" do
183
- @database.stub(:send_request).with("/simple/by-example", put: {"collection" => "example_1", "skip" => 1, "example" => { :hello => "world"}}).and_return { server_response('simple-queries/example') }
184
- @database.should_receive(:send_request).with("/simple/by-example", put: {"collection" => "example_1", "skip" => 1, "example" => { :hello => "world"}})
185
-
186
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
187
-
188
- subject.by_example @search_params, :skip => 1
189
- end
190
-
279
+ @database.stub(:send_request).with("/simple/by-example", put:
280
+ {"collection" => "example_1", "skip" => 1, "example" => { :hello => "world"}}
281
+ ).and_return { server_response('simple-queries/example') }
282
+ @database.should_receive(:send_request).with("/simple/by-example", put:
283
+ {"collection" => "example_1", "skip" => 1, "example" => { :hello => "world"}})
284
+
285
+ Ashikawa::Core::Cursor.should_receive(:new)
286
+
287
+ subject.by_example example: @example, :skip => 1
288
+ end
289
+
191
290
  it "should limit documents" do
192
291
  @database.stub(:send_request).with("/simple/by-example", put: {"collection" => "example_1", "limit" => 2, "example" => { :hello => "world"}}).and_return { server_response('simple-queries/example') }
193
292
  @database.should_receive(:send_request).with("/simple/by-example", put: {"collection" => "example_1", "limit" => 2, "example" => { :hello => "world"}})
194
-
195
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
196
-
197
- subject.by_example @search_params, :limit => 2
293
+
294
+ Ashikawa::Core::Cursor.should_receive(:new)
295
+
296
+ subject.by_example example: @example, :limit => 2
198
297
  end
199
-
200
298
  end
201
299
 
202
300
  describe "near" do
@@ -204,9 +302,7 @@ describe Ashikawa::Core::Collection do
204
302
  @database.stub(:send_request).with("/simple/near", put: { "collection" => "example_1", "latitude" => 0, "longitude" => 0 }).and_return { server_response('simple-queries/near') }
205
303
  @database.should_receive(:send_request).with("/simple/near", put: { "collection" => "example_1", "latitude" => 0, "longitude" => 0 })
206
304
 
207
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
208
- Ashikawa::Core::Document.should_receive(:new).with("12346/2938", 2938)
209
- Ashikawa::Core::Document.should_receive(:new).with("12347/23737", 23737)
305
+ Ashikawa::Core::Cursor.should_receive(:new)
210
306
 
211
307
  subject.near :latitude => 0, :longitude => 0
212
308
  end
@@ -217,12 +313,23 @@ describe Ashikawa::Core::Collection do
217
313
  @database.stub(:send_request).with("/simple/within", put: { "collection" => "example_1", "latitude" => 0, "longitude" => 0, "radius" => 2 }).and_return { server_response('simple-queries/within') }
218
314
  @database.should_receive(:send_request).with("/simple/within" , put: { "collection" => "example_1", "latitude" => 0, "longitude" => 0, "radius" => 2 })
219
315
 
220
- Ashikawa::Core::Document.should_receive(:new).with("12345/57463", 57463)
316
+ Ashikawa::Core::Cursor.should_receive(:new)
221
317
 
222
318
  subject.within :latitude => 0, :longitude => 0, :radius => 2
223
319
  end
224
320
  end
225
321
 
322
+ describe "in range" do
323
+ it "should look for documents with an attribute within a certain range" do
324
+ arguments = { "collection" => "example_1", "attribute" => "age", "left" => 50, "right" => 60, "closed" => false}
325
+ @database.stub(:send_request).with("/simple/range", put: arguments).and_return { server_response('simple-queries/range') }
326
+ @database.should_receive(:send_request).with("/simple/range" , put: arguments)
327
+
328
+ Ashikawa::Core::Cursor.should_receive(:new)
329
+
330
+ subject.in_range attribute: "age", left: 50, right: 60, closed: false
331
+ end
332
+ end
226
333
  end
227
334
  end
228
335
  end
@@ -3,52 +3,52 @@ require 'ashikawa-core/connection'
3
3
 
4
4
  describe Ashikawa::Core::Connection do
5
5
  subject { Ashikawa::Core::Connection }
6
-
6
+
7
7
  it "should have an IP and port" do
8
8
  connection = subject.new "http://localhost:8529"
9
-
9
+
10
10
  connection.ip.should == "http://localhost"
11
11
  connection.port.should == 8529
12
12
  end
13
-
13
+
14
14
  describe "initialized connection" do
15
15
  subject { Ashikawa::Core::Connection.new "http://localhost:8529" }
16
-
16
+
17
17
  it "should send a get request" do
18
18
  stub_request(:get, "http://localhost:8529/_api/my/path").to_return body: '{ "name": "dude" }'
19
-
19
+
20
20
  subject.send_request "/my/path"
21
-
21
+
22
22
  WebMock.should have_requested(:get, "http://localhost:8529/_api/my/path")
23
23
  end
24
-
24
+
25
25
  it "should send a post request" do
26
26
  stub_request(:post, "http://localhost:8529/_api/my/path").with(:body => '{"name":"new_collection"}').to_return body: '{ "name": "dude" }'
27
-
27
+
28
28
  subject.send_request "/my/path", post: { :name => 'new_collection' }
29
-
29
+
30
30
  WebMock.should have_requested(:post, "http://localhost:8529/_api/my/path").with :body => '{"name":"new_collection"}'
31
31
  end
32
-
32
+
33
33
  it "should send a put request" do
34
34
  stub_request(:put, "http://localhost:8529/_api/my/path").with(:body => '{"name":"new_collection"}').to_return body: '{ "name": "dude" }'
35
-
35
+
36
36
  subject.send_request "/my/path", put: { :name => 'new_collection' }
37
-
37
+
38
38
  WebMock.should have_requested(:put, "http://localhost:8529/_api/my/path").with :body => '{"name":"new_collection"}'
39
39
  end
40
-
40
+
41
41
  it "should send a delete request" do
42
42
  stub_request(:delete, "http://localhost:8529/_api/my/path").to_return body: '{ "name": "dude" }'
43
-
43
+
44
44
  subject.send_request "/my/path", delete: { }
45
-
45
+
46
46
  WebMock.should have_requested(:delete, "http://localhost:8529/_api/my/path")
47
47
  end
48
-
48
+
49
49
  it "should parse JSON" do
50
50
  stub_request(:get, "http://localhost:8529/_api/my/path").to_return body: '{ "name": "dude" }'
51
-
51
+
52
52
  subject.send_request("/my/path").should == {"name" => "dude"}
53
53
  end
54
54
  end