ashikawa-core 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/.rspec +0 -1
  2. data/.travis.yml +2 -0
  3. data/CONTRIBUTING.md +14 -29
  4. data/Gemfile.devtools +9 -10
  5. data/README.md +30 -9
  6. data/Rakefile +1 -1
  7. data/ashikawa-core.gemspec +9 -8
  8. data/config/flay.yml +2 -2
  9. data/config/flog.yml +1 -1
  10. data/config/roodi.yml +4 -5
  11. data/config/site.reek +40 -16
  12. data/config/yardstick.yml +1 -1
  13. data/lib/ashikawa-core/collection.rb +109 -22
  14. data/lib/ashikawa-core/connection.rb +42 -110
  15. data/lib/ashikawa-core/cursor.rb +13 -6
  16. data/lib/ashikawa-core/database.rb +67 -17
  17. data/lib/ashikawa-core/document.rb +41 -10
  18. data/lib/ashikawa-core/edge.rb +50 -0
  19. data/lib/ashikawa-core/exceptions/client_error/bad_syntax.rb +24 -0
  20. data/lib/ashikawa-core/exceptions/{collection_not_found.rb → client_error/resource_not_found/collection_not_found.rb} +3 -1
  21. data/lib/ashikawa-core/exceptions/{document_not_found.rb → client_error/resource_not_found/document_not_found.rb} +3 -1
  22. data/lib/ashikawa-core/exceptions/{index_not_found.rb → client_error/resource_not_found/index_not_found.rb} +3 -1
  23. data/lib/ashikawa-core/exceptions/client_error/resource_not_found.rb +25 -0
  24. data/lib/ashikawa-core/exceptions/client_error.rb +23 -0
  25. data/lib/ashikawa-core/exceptions/server_error/json_error.rb +25 -0
  26. data/lib/ashikawa-core/exceptions/server_error.rb +23 -0
  27. data/lib/ashikawa-core/figure.rb +59 -2
  28. data/lib/ashikawa-core/index.rb +23 -7
  29. data/lib/ashikawa-core/query.rb +10 -10
  30. data/lib/ashikawa-core/request_preprocessor.rb +49 -0
  31. data/lib/ashikawa-core/response_preprocessor.rb +111 -0
  32. data/lib/ashikawa-core/version.rb +1 -1
  33. data/lib/ashikawa-core.rb +0 -1
  34. data/spec/acceptance/basic_spec.rb +61 -22
  35. data/spec/acceptance/index_spec.rb +11 -4
  36. data/spec/acceptance/query_spec.rb +4 -1
  37. data/spec/acceptance/spec_helper.rb +0 -2
  38. data/spec/acceptance_auth/spec_helper.rb +0 -2
  39. data/spec/fixtures/collections/60768679-count.json +13 -0
  40. data/spec/fixtures/collections/60768679-figures.json +35 -0
  41. data/spec/fixtures/collections/60768679-properties-volatile.json +12 -0
  42. data/spec/fixtures/collections/60768679-properties.json +12 -0
  43. data/spec/fixtures/collections/{4588.json → 60768679.json} +2 -2
  44. data/spec/fixtures/collections/all.json +5 -5
  45. data/spec/fixtures/cursor/26011191-2.json +1 -1
  46. data/spec/fixtures/cursor/26011191.json +1 -1
  47. data/spec/fixtures/documents/example_1-137249191.json +6 -0
  48. data/spec/fixtures/documents/new-example_1-137249191.json +6 -0
  49. data/spec/setup/arangodb.sh +1 -1
  50. data/spec/unit/collection_spec.rb +117 -42
  51. data/spec/unit/connection_spec.rb +161 -61
  52. data/spec/unit/cursor_spec.rb +39 -12
  53. data/spec/unit/database_spec.rb +119 -19
  54. data/spec/unit/document_spec.rb +4 -2
  55. data/spec/unit/edge_spec.rb +54 -0
  56. data/spec/unit/exception_spec.rb +36 -8
  57. data/spec/unit/figure_spec.rb +37 -11
  58. data/spec/unit/index_spec.rb +1 -1
  59. data/spec/unit/query_spec.rb +18 -18
  60. data/spec/unit/spec_helper.rb +4 -13
  61. data/tasks/adjustments.rake +3 -2
  62. metadata +59 -32
  63. data/lib/ashikawa-core/exceptions/unknown_path.rb +0 -15
  64. data/spec/fixtures/collections/4590-properties.json +0 -9
  65. data/spec/fixtures/collections/4590.json +0 -8
  66. data/spec/fixtures/collections/73482-figures.json +0 -23
  67. data/spec/fixtures/documents/4590-333.json +0 -5
  68. data/spec/fixtures/documents/new-4590-333.json +0 -5
@@ -10,31 +10,31 @@ describe Ashikawa::Core::Cursor do
10
10
  end
11
11
 
12
12
  it "should create a cursor for a non-complete batch" do
13
- my_cursor = subject.new @database, server_response("/cursor/26011191")
14
- my_cursor.id.should == 26011191
13
+ my_cursor = subject.new @database, server_response("cursor/26011191")
14
+ my_cursor.id.should == "26011191"
15
15
  my_cursor.length.should == 5
16
16
  end
17
17
 
18
18
  it "should create a cursor for the last batch" do
19
- my_cursor = subject.new @database, server_response("/cursor/26011191-3")
19
+ my_cursor = subject.new @database, server_response("cursor/26011191-3")
20
20
  my_cursor.id.should be_nil
21
21
  my_cursor.length.should == 5
22
22
  end
23
23
 
24
24
  describe "existing cursor" do
25
25
  subject { Ashikawa::Core::Cursor.new @database,
26
- server_response("/cursor/26011191")
26
+ server_response("cursor/26011191")
27
27
  }
28
28
 
29
- it "should iterate over all documents of a cursor" do
29
+ it "should iterate over all documents of a cursor when given a block" do
30
30
  first = true
31
31
 
32
- @database.stub(:send_request).with("/cursor/26011191", :put => {}) do
32
+ @database.stub(:send_request).with("cursor/26011191", :put => {}) do
33
33
  if first
34
34
  first = false
35
- server_response("/cursor/26011191-2")
35
+ server_response("cursor/26011191-2")
36
36
  else
37
- server_response("/cursor/26011191-3")
37
+ server_response("cursor/26011191-3")
38
38
  end
39
39
  end
40
40
  @database.should_receive(:send_request).twice
@@ -45,9 +45,36 @@ describe Ashikawa::Core::Cursor do
45
45
  subject.each { |document| }
46
46
  end
47
47
 
48
+ it "should return an enumerator to go over all documents of a cursor when given no block" do
49
+ pending "This fails on 1.8.7 because of an old backports version" if RUBY_VERSION == "1.8.7"
50
+
51
+ first = true
52
+
53
+ @database.stub(:send_request).with("cursor/26011191", :put => {}) do
54
+ if first
55
+ first = false
56
+ server_response("cursor/26011191-2")
57
+ else
58
+ server_response("cursor/26011191-3")
59
+ end
60
+ end
61
+ @database.should_receive(:send_request).twice
62
+
63
+ Ashikawa::Core::Document.stub(:new)
64
+ Ashikawa::Core::Document.should_receive(:new).exactly(5).times
65
+
66
+ enumerator = subject.each
67
+ enumerator.next
68
+ enumerator.next
69
+ enumerator.next
70
+ enumerator.next
71
+ enumerator.next
72
+ expect { enumerator.next }.to raise_exception(StopIteration)
73
+ end
74
+
48
75
  it "should be deletable" do
49
76
  @database.stub(:send_request)
50
- @database.should_receive(:send_request).with("/cursor/26011191",
77
+ @database.should_receive(:send_request).with("cursor/26011191",
51
78
  :delete => {})
52
79
 
53
80
  subject.delete
@@ -56,12 +83,12 @@ describe Ashikawa::Core::Cursor do
56
83
  it "should be enumerable" do
57
84
  first = true
58
85
 
59
- @database.stub(:send_request).with("/cursor/26011191", :put => {}) do
86
+ @database.stub(:send_request).with("cursor/26011191", :put => {}) do
60
87
  if first
61
88
  first = false
62
- server_response("/cursor/26011191-2")
89
+ server_response("cursor/26011191-2")
63
90
  else
64
- server_response("/cursor/26011191-3")
91
+ server_response("cursor/26011191-3")
65
92
  end
66
93
  end
67
94
  @database.should_receive(:send_request).twice
@@ -15,20 +15,78 @@ describe Ashikawa::Core::Database do
15
15
  @connection.stub(:host) { "localhost" }
16
16
  @connection.stub(:port) { 8529 }
17
17
 
18
- database = subject.new @connection
18
+ database = subject.new do |config|
19
+ config.connection = @connection
20
+ end
19
21
  database.host.should == "localhost"
20
22
  database.port.should == 8529
21
23
  end
22
24
 
23
25
  it "should initialize with a connection string" do
24
- Ashikawa::Core::Connection.stub(:new).with("http://localhost:8529").and_return(double())
25
- Ashikawa::Core::Connection.should_receive(:new).with("http://localhost:8529")
26
+ Ashikawa::Core::Connection.stub(:new).with("http://localhost:8529", {
27
+ :logger => nil,
28
+ :adapter => nil
29
+ }).and_return(double())
30
+ Ashikawa::Core::Connection.should_receive(:new).with("http://localhost:8529", {
31
+ :logger => nil,
32
+ :adapter => nil
33
+ })
34
+
35
+ database = subject.new do |config|
36
+ config.url = "http://localhost:8529"
37
+ end
38
+ end
39
+
40
+ it "should initialize with a connection string and logger" do
41
+ logger = double
42
+ Ashikawa::Core::Connection.stub(:new).with("http://localhost:8529", {
43
+ :logger => logger,
44
+ :adapter => nil
45
+ }).and_return(double())
46
+ Ashikawa::Core::Connection.should_receive(:new).with("http://localhost:8529", {
47
+ :logger => logger,
48
+ :adapter => nil
49
+ })
50
+
51
+ database = subject.new do |config|
52
+ config.url = "http://localhost:8529"
53
+ config.logger = logger
54
+ end
55
+ end
26
56
 
27
- database = subject.new "http://localhost:8529"
57
+ it "should initialize with a connection string and adapter" do
58
+ adapter = double
59
+ Ashikawa::Core::Connection.stub(:new).with("http://localhost:8529", {
60
+ :logger => nil,
61
+ :adapter => adapter
62
+ }).and_return(double())
63
+ Ashikawa::Core::Connection.should_receive(:new).with("http://localhost:8529", {
64
+ :logger => nil,
65
+ :adapter => adapter
66
+ })
67
+
68
+ database = subject.new do |config|
69
+ config.url = "http://localhost:8529"
70
+ config.adapter = adapter
71
+ end
72
+ end
73
+
74
+ it "should throw an argument error when neither url nor connection was provided" do
75
+ adapter = double
76
+ logger = double
77
+
78
+ expect {
79
+ database = subject.new do |config|
80
+ config.adapter = adapter
81
+ config.logger = logger
82
+ end
83
+ }.to raise_error(ArgumentError, /either an url or a connection/)
28
84
  end
29
85
 
30
86
  it "should create a query" do
31
- database = subject.new @connection
87
+ database = subject.new do |config|
88
+ config.connection = @connection
89
+ end
32
90
 
33
91
  mock Ashikawa::Core::Query
34
92
  Ashikawa::Core::Query.stub(:new)
@@ -38,7 +96,10 @@ describe Ashikawa::Core::Database do
38
96
  end
39
97
 
40
98
  describe "initialized database" do
41
- subject { Ashikawa::Core::Database.new @connection }
99
+ subject { Ashikawa::Core::Database.new do |config|
100
+ config.connection = @connection
101
+ end
102
+ }
42
103
 
43
104
  it "should delegate authentication to the connection" do
44
105
  @connection.should_receive(:authenticate_with).with({ :username => "user", :password => "password" })
@@ -48,44 +109,83 @@ describe Ashikawa::Core::Database do
48
109
 
49
110
  it "should fetch all available collections" do
50
111
  @connection.stub(:send_request) {|path| server_response("collections/all") }
51
- @connection.should_receive(:send_request).with("/collection")
112
+ @connection.should_receive(:send_request).with("collection")
52
113
 
53
- Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("/collections/all")["collections"][0])
54
- Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("/collections/all")["collections"][1])
114
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/all")["collections"][0])
115
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/all")["collections"][1])
55
116
 
56
117
  subject.collections.length.should == 2
57
118
  end
58
119
 
120
+ it "should create a non volatile collection by default" do
121
+ @connection.stub(:send_request) { |path| server_response("collections/60768679") }
122
+ @connection.should_receive(:send_request).with("collection",
123
+ :post => { :name => "volatile_collection"})
124
+
125
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/60768679"))
126
+
127
+ subject.create_collection("volatile_collection")
128
+ end
129
+
130
+ it "should create a volatile collection when asked" do
131
+ @connection.stub(:send_request) { |path| server_response("collections/60768679") }
132
+ @connection.should_receive(:send_request).with("collection",
133
+ :post => { :name => "volatile_collection", :isVolatile => true})
134
+
135
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/60768679"))
136
+
137
+ subject.create_collection("volatile_collection", :is_volatile => true)
138
+ end
139
+
140
+ it "should create an edge collection when asked" do
141
+ @connection.stub(:send_request) { |path| server_response("collections/60768679") }
142
+ @connection.should_receive(:send_request).with("collection",
143
+ :post => { :name => "volatile_collection", :type => 3})
144
+
145
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/60768679"))
146
+
147
+ subject.create_collection("volatile_collection", :content_type => :edge)
148
+ end
149
+
59
150
  it "should fetch a single collection if it exists" do
60
- @connection.stub(:send_request) { |path| server_response("collections/4588") }
61
- @connection.should_receive(:send_request).with("/collection/4588")
151
+ @connection.stub(:send_request) { |path| server_response("collections/60768679") }
152
+ @connection.should_receive(:send_request).with("collection/60768679")
153
+
154
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/60768679"))
155
+
156
+ subject.collection(60768679)
157
+ end
158
+
159
+ it "should fetch a single collection with the array syntax" do
160
+ @connection.stub(:send_request) { |path| server_response("collections/60768679") }
161
+ @connection.should_receive(:send_request).with("collection/60768679")
62
162
 
63
- Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("/collections/4588"))
163
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/60768679"))
64
164
 
65
- subject[4588]
165
+ subject[60768679]
66
166
  end
67
167
 
68
168
  it "should create a single collection if it doesn't exist" do
69
169
  @connection.stub :send_request do |path, method|
70
170
  method ||= {}
71
171
  if method.has_key? :post
72
- server_response("collections/4590")
172
+ server_response("collections/60768679")
73
173
  else
74
174
  raise Ashikawa::Core::CollectionNotFoundException
75
175
  end
76
176
  end
77
- @connection.should_receive(:send_request).with("/collection/new_collection")
78
- @connection.should_receive(:send_request).with("/collection", :post => { :name => "new_collection"} )
177
+ @connection.should_receive(:send_request).with("collection/new_collection")
178
+ @connection.should_receive(:send_request).with("collection", :post => { :name => "new_collection"} )
79
179
 
80
- Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/4590"))
180
+ Ashikawa::Core::Collection.should_receive(:new).with(subject, server_response("collections/60768679"))
81
181
 
82
182
  subject['new_collection']
83
183
  end
84
184
 
85
185
  it "should send a request via the connection object" do
86
- @connection.should_receive(:send_request).with("/my/path", :post => { :data => "mydata" })
186
+ @connection.should_receive(:send_request).with("my/path", :post => { :data => "mydata" })
87
187
 
88
- subject.send_request "/my/path", :post => { :data => "mydata" }
188
+ subject.send_request "my/path", :post => { :data => "mydata" }
89
189
  end
90
190
  end
91
191
  end
@@ -6,6 +6,7 @@ describe Ashikawa::Core::Document do
6
6
  let(:raw_data) {
7
7
  {
8
8
  "_id" => "1234567/2345678",
9
+ "_key" => "2345678",
9
10
  "_rev" => "3456789",
10
11
  "first_name" => "The",
11
12
  "last_name" => "Dude"
@@ -21,8 +22,9 @@ describe Ashikawa::Core::Document do
21
22
 
22
23
  it "should initialize data with ID" do
23
24
  document = subject.new database, raw_data
24
- document.id.should == 2345678
25
- document.revision.should == 3456789
25
+ document.id.should == "1234567/2345678"
26
+ document.key.should == "2345678"
27
+ document.revision.should == "3456789"
26
28
  end
27
29
 
28
30
  it "should initialize data without ID" do
@@ -0,0 +1,54 @@
1
+ require 'unit/spec_helper'
2
+ require 'ashikawa-core/edge'
3
+
4
+ describe Ashikawa::Core::Edge do
5
+ let(:database) { double() }
6
+ let(:raw_data) {
7
+ {
8
+ "_id" => "1234567/2345678",
9
+ "_key" => "2345678",
10
+ "_rev" => "3456789",
11
+ "_from" => "7848004/9289796",
12
+ "_to" => "7848004/9355332",
13
+ "first_name" => "The",
14
+ "last_name" => "Dude"
15
+ }
16
+ }
17
+ subject { Ashikawa::Core::Edge }
18
+
19
+ it "should initialize data" do
20
+ document = subject.new(database, raw_data)
21
+ document.id.should == "1234567/2345678"
22
+ document.key.should == "2345678"
23
+ document.revision.should == "3456789"
24
+ end
25
+
26
+ describe "initialized edge" do
27
+ subject { Ashikawa::Core::Edge.new(database, raw_data)}
28
+
29
+ it "should be deletable" do
30
+ database.should_receive(:send_request).with("edge/#{raw_data['_id']}",
31
+ { :delete => {} }
32
+ )
33
+
34
+ subject.delete
35
+ end
36
+
37
+ it "should store changes to the database" do
38
+ database.should_receive(:send_request).with("edge/#{raw_data['_id']}",
39
+ { :put => { "first_name" => "The", "last_name" => "Other" } }
40
+ )
41
+
42
+ subject["last_name"] = "Other"
43
+ subject.save
44
+ end
45
+
46
+ it "should know the ID of the 'from' document" do
47
+ subject.from_id.should == "7848004/9289796"
48
+ end
49
+
50
+ it "should know the ID of the 'to' document" do
51
+ subject.to_id.should == "7848004/9355332"
52
+ end
53
+ end
54
+ end
@@ -1,8 +1,36 @@
1
- require "ashikawa-core/exceptions/document_not_found"
2
- require "ashikawa-core/exceptions/collection_not_found"
3
- require "ashikawa-core/exceptions/index_not_found"
4
1
  require "ashikawa-core/exceptions/no_collection_provided"
5
- require "ashikawa-core/exceptions/unknown_path"
2
+ require "ashikawa-core/exceptions/client_error"
3
+ require "ashikawa-core/exceptions/client_error/bad_syntax"
4
+ require "ashikawa-core/exceptions/client_error/resource_not_found"
5
+ require "ashikawa-core/exceptions/client_error/resource_not_found/document_not_found"
6
+ require "ashikawa-core/exceptions/client_error/resource_not_found/collection_not_found"
7
+ require "ashikawa-core/exceptions/client_error/resource_not_found/index_not_found"
8
+ require "ashikawa-core/exceptions/server_error"
9
+ require "ashikawa-core/exceptions/server_error/json_error"
10
+
11
+ describe Ashikawa::Core::NoCollectionProvidedException do
12
+ it "should have a good explanation" do
13
+ subject.to_s.should include "without a collection"
14
+ end
15
+ end
16
+
17
+ describe Ashikawa::Core::ClientError do
18
+ it "should have a good explanation" do
19
+ Ashikawa::Core::ClientError.new(411).to_s.should include "client"
20
+ end
21
+ end
22
+
23
+ describe Ashikawa::Core::BadSyntax do
24
+ it "should have a good explanation" do
25
+ subject.to_s.should include "syntax"
26
+ end
27
+ end
28
+
29
+ describe Ashikawa::Core::ResourceNotFound do
30
+ it "should have a good explanation" do
31
+ subject.to_s.should include "was not found"
32
+ end
33
+ end
6
34
 
7
35
  describe Ashikawa::Core::DocumentNotFoundException do
8
36
  it "should have a good explanation" do
@@ -22,14 +50,14 @@ describe Ashikawa::Core::IndexNotFoundException do
22
50
  end
23
51
  end
24
52
 
25
- describe Ashikawa::Core::NoCollectionProvidedException do
53
+ describe Ashikawa::Core::ServerError do
26
54
  it "should have a good explanation" do
27
- subject.to_s.should include "without a collection"
55
+ Ashikawa::Core::ServerError.new(511).to_s.should include "server"
28
56
  end
29
57
  end
30
58
 
31
- describe Ashikawa::Core::UnknownPath do
59
+ describe Ashikawa::Core::JsonError do
32
60
  it "should have a good explanation" do
33
- subject.to_s.should include "path is unknown"
61
+ subject.to_s.should include "JSON from the server"
34
62
  end
35
63
  end
@@ -3,26 +3,52 @@ require "ashikawa-core/figure"
3
3
  describe Ashikawa::Core::Figure do
4
4
  let(:raw_figures) {
5
5
  {
6
- "datafiles" => {
7
- "count" => 1
8
- },
9
6
  "alive" => {
10
7
  "size" => 0,
11
8
  "count" => 0
12
9
  },
13
10
  "dead" => {
14
11
  "size" => 2384,
15
- "count" => 149
12
+ "count" => 149,
13
+ "deletion" => 0
14
+ },
15
+ "datafiles" => {
16
+ "count" => 1,
17
+ "fileSize" => 124
18
+ },
19
+ "journals" => {
20
+ "count" => 1,
21
+ "fileSize" => 124
22
+ },
23
+ "shapes" => {
24
+ "count" => 2
16
25
  }
17
26
  }
18
27
  }
19
- subject { Ashikawa::Core::Figure.new raw_figures }
28
+ subject { Ashikawa::Core::Figure.new(raw_figures) }
29
+
30
+ it "should check for the alive figures" do
31
+ subject.alive_size.should == 0
32
+ subject.alive_count.should == 0
33
+ end
34
+
35
+ it "should check for the dead figures" do
36
+ subject.dead_size.should == 2384
37
+ subject.dead_count.should == 149
38
+ subject.dead_deletion.should == 0
39
+ end
40
+
41
+ it "should check for the datafiles figures" do
42
+ subject.datafiles_count.should == 1
43
+ subject.datafiles_file_size.should == 124
44
+ end
45
+
46
+ it "should check for the journal figures" do
47
+ subject.journals_count.should == 1
48
+ subject.journals_file_size.should == 124
49
+ end
20
50
 
21
- it "should check for the figures" do
22
- subject.datafiles_count.should == 1
23
- subject.alive_size.should == 0
24
- subject.alive_count.should == 0
25
- subject.dead_size.should == 2384
26
- subject.dead_count.should == 149
51
+ it "should check for the shapes figure" do
52
+ subject.shapes_count.should == 2
27
53
  end
28
54
  end