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.
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