ashikawa-core 0.6.0 → 0.7.0

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 (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
@@ -0,0 +1,50 @@
1
+ require 'ashikawa-core/document'
2
+
3
+ module Ashikawa
4
+ module Core
5
+ # A certain Edge within a certain Collection
6
+ class Edge < Document
7
+ # The ID of the 'from' document
8
+ #
9
+ # @return [String]
10
+ # @api public
11
+ # @example Get the ID for the 'from' Document
12
+ # document = Ashikawa::Core::Edge.new(database, raw_document)
13
+ # document.from_id # => "my_fancy_collection/2345678"
14
+ attr_reader :from_id
15
+
16
+ # The ID of the 'to' document
17
+ #
18
+ # @return [String]
19
+ # @api public
20
+ # @example Get the ID for the 'to' Document
21
+ # document = Ashikawa::Core::Edge.new(database, raw_document)
22
+ # document.to_id # => "my_fancy_collection/2345678"
23
+ attr_reader :to_id
24
+
25
+ # Initialize an Edge with the database and raw data
26
+ #
27
+ # @param [Database] database
28
+ # @param [Hash] raw_edge
29
+ # @api public
30
+ # @example Create an Edge
31
+ # document = Ashikawa::Core::Edge.new(database, raw_edge)
32
+ def initialize(database, raw_edge)
33
+ @from_id = raw_edge["_from"]
34
+ @to_id = raw_edge["_to"]
35
+ super(database, raw_edge)
36
+ end
37
+
38
+ protected
39
+
40
+ # Send a request for this edge with the given opts
41
+ #
42
+ # @param [Hash] opts Options for this request
43
+ # @return [Hash] The parsed response from the server
44
+ # @api private
45
+ def send_request_for_document(opts = {})
46
+ @database.send_request("edge/#{@id}", opts)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ require "ashikawa-core/exceptions/client_error.rb"
2
+
3
+ module Ashikawa
4
+ module Core
5
+ # This exception is thrown when the client used bad syntax in a request
6
+ class BadSyntax < ClientError
7
+ # Create a new instance
8
+ #
9
+ # @return RuntimeError
10
+ # @api private
11
+ def initialize
12
+ super(400)
13
+ end
14
+
15
+ # String representation of the exception
16
+ #
17
+ # @return String
18
+ # @api private
19
+ def to_s
20
+ "Status 400: The syntax of the request was bad"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,8 +1,10 @@
1
+ require "ashikawa-core/exceptions/client_error/resource_not_found"
2
+
1
3
  module Ashikawa
2
4
  module Core
3
5
  # This Exception is thrown when a document was requested from
4
6
  # the server that does not exist.
5
- class CollectionNotFoundException < RuntimeError
7
+ class CollectionNotFoundException < ResourceNotFound
6
8
  # String representation of the exception
7
9
  #
8
10
  # @return String
@@ -1,8 +1,10 @@
1
+ require "ashikawa-core/exceptions/client_error/resource_not_found"
2
+
1
3
  module Ashikawa
2
4
  module Core
3
5
  # This Exception is thrown when a document was requested from
4
6
  # the server that does not exist.
5
- class DocumentNotFoundException < RuntimeError
7
+ class DocumentNotFoundException < ResourceNotFound
6
8
  # String representation of the exception
7
9
  #
8
10
  # @return String
@@ -1,8 +1,10 @@
1
+ require "ashikawa-core/exceptions/client_error/resource_not_found"
2
+
1
3
  module Ashikawa
2
4
  module Core
3
5
  # This Exception is thrown when an index was requested from
4
6
  # the server that does not exist.
5
- class IndexNotFoundException < RuntimeError
7
+ class IndexNotFoundException < ResourceNotFound
6
8
  # String representation of the exception
7
9
  #
8
10
  # @return String
@@ -0,0 +1,25 @@
1
+ require "ashikawa-core/exceptions/client_error.rb"
2
+
3
+ module Ashikawa
4
+ module Core
5
+ # This Exception is thrown when you request
6
+ # a resource that does not exist on the server
7
+ class ResourceNotFound < ClientError
8
+ # Create a new instance
9
+ #
10
+ # @return RuntimeError
11
+ # @api private
12
+ def initialize
13
+ super(404)
14
+ end
15
+
16
+ # String representation of the exception
17
+ #
18
+ # @return String
19
+ # @api private
20
+ def to_s
21
+ "Status 404: The Resource you requested was not found on the server"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ module Ashikawa
2
+ module Core
3
+ # The client had an error in the request
4
+ class ClientError < RuntimeError
5
+ # Create a new instance
6
+ #
7
+ # @param [Integer] status
8
+ # @return RuntimeError
9
+ # @api private
10
+ def initialize(status)
11
+ @status = status
12
+ end
13
+
14
+ # String representation of the exception
15
+ #
16
+ # @return String
17
+ # @api private
18
+ def to_s
19
+ "Status #{@status}: An Error occured in the client"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ require "ashikawa-core/exceptions/server_error"
2
+
3
+ module Ashikawa
4
+ module Core
5
+ # This Exception is thrown when the Json
6
+ # from the server was malformed
7
+ class JsonError < ServerError
8
+ # Create a new instance
9
+ #
10
+ # @return RuntimeError
11
+ # @api private
12
+ def initialize
13
+ super(nil)
14
+ end
15
+
16
+ # String representation of the exception
17
+ #
18
+ # @return String
19
+ # @api private
20
+ def to_s
21
+ "Either the JSON from the server was malformed or the content type incorrect"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ module Ashikawa
2
+ module Core
3
+ # The server had an error during the request
4
+ class ServerError < RuntimeError
5
+ # Create a new instance
6
+ #
7
+ # @param [Integer] status
8
+ # @return RuntimeError
9
+ # @api private
10
+ def initialize(status)
11
+ @status = status
12
+ end
13
+
14
+ # String representation of the exception
15
+ #
16
+ # @return String
17
+ # @api private
18
+ def to_s
19
+ "Status #{@status}: An Error occured on the server"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -10,8 +10,10 @@ module Ashikawa
10
10
  # figure = Ashikawa::Core::Figure.new(raw_figure)
11
11
  def initialize(raw_figure)
12
12
  @datafiles = raw_figure["datafiles"]
13
- @alive = raw_figure["alive"]
14
- @dead = raw_figure["dead"]
13
+ @alive = raw_figure["alive"]
14
+ @dead = raw_figure["dead"]
15
+ @shapes = raw_figure["shapes"]
16
+ @journals = raw_figure["journals"]
15
17
  end
16
18
 
17
19
  # The number of active datafiles
@@ -25,6 +27,17 @@ module Ashikawa
25
27
  @datafiles["count"]
26
28
  end
27
29
 
30
+ # The file size of datafiles
31
+ #
32
+ # @return Fixnum
33
+ # @api public
34
+ # @example Get the file size of datafiles
35
+ # figure = Ashikawa::Core::Figure.new(raw_figure)
36
+ # figure.datafile_size #=> 1337
37
+ def datafiles_file_size
38
+ @datafiles["fileSize"]
39
+ end
40
+
28
41
  # The total size in bytes used by all living documents
29
42
  #
30
43
  # @return Fixnum
@@ -68,6 +81,50 @@ module Ashikawa
68
81
  def dead_count
69
82
  @dead["count"]
70
83
  end
84
+
85
+ # The total number of shapes used in the collection
86
+ #
87
+ # @return Fixnum
88
+ # @api public
89
+ # @example Get the number of shapes
90
+ # figure = Ashikawa::Core::Figure.new(raw_figure)
91
+ # figure.shapes_count #=> 1337
92
+ def shapes_count
93
+ @shapes["count"]
94
+ end
95
+
96
+ # The number of deletion markers
97
+ #
98
+ # @return Fixnum
99
+ # @api public
100
+ # @example Get the number of deletion markers
101
+ # figure = Ashikawa::Core::Figure.new(raw_figure)
102
+ # figure.dead_deletion #=> 1337
103
+ def dead_deletion
104
+ @dead["deletion"]
105
+ end
106
+
107
+ # The number of journals
108
+ #
109
+ # @return Fixnum
110
+ # @api public
111
+ # @example Get the number of journals
112
+ # figure = Ashikawa::Core::Figure.new(raw_figure)
113
+ # figure.journal_count #=> 1337
114
+ def journals_count
115
+ @journals["count"]
116
+ end
117
+
118
+ # The file size of journals
119
+ #
120
+ # @return Fixnum
121
+ # @api public
122
+ # @example Get the file size of journals
123
+ # figure = Ashikawa::Core::Figure.new(raw_figure)
124
+ # figure.journal_size #=> 1337
125
+ def journals_file_size
126
+ @journals["fileSize"]
127
+ end
71
128
  end
72
129
  end
73
130
  end
@@ -3,6 +3,7 @@ module Ashikawa
3
3
  # An index on a certain collection
4
4
  class Index
5
5
  # The fields the index is defined on as symbols
6
+ #
6
7
  # @return [Array<Symbol>]
7
8
  # @api public
8
9
  # @example Get the fields the index is set on
@@ -11,6 +12,7 @@ module Ashikawa
11
12
  attr_reader :on
12
13
 
13
14
  # The type of index as a symbol
15
+ #
14
16
  # @return [Symbol]
15
17
  # @api public
16
18
  # @example Get the type of the index
@@ -19,6 +21,7 @@ module Ashikawa
19
21
  attr_reader :type
20
22
 
21
23
  # Is the unique constraint set?
24
+ #
22
25
  # @return [Boolean]
23
26
  # @api public
24
27
  # @example Get the fields the index is set on
@@ -26,8 +29,9 @@ module Ashikawa
26
29
  # index.unique #=> false
27
30
  attr_reader :unique
28
31
 
29
- # The id of the index
30
- # @return [Int]
32
+ # The ID of the index (includes a Collection prefix)
33
+ #
34
+ # @return [String]
31
35
  # @api public
32
36
  # @example Get the id of this index
33
37
  # index = Ashikawa::Core::Index.new(collection, raw_index)
@@ -44,10 +48,7 @@ module Ashikawa
44
48
  # index = Ashikawa::Core::Index.new(collection, raw_index)
45
49
  def initialize(collection, raw_index)
46
50
  @collection = collection
47
- @id = raw_index["id"].split("/")[1].to_i if raw_index.has_key?("id")
48
- @on = raw_index["fields"].map { |field| field.to_sym } if raw_index.has_key?("fields")
49
- @type = raw_index["type"].to_sym if raw_index.has_key?("type")
50
- @unique = raw_index["unique"] if raw_index.has_key?("unique")
51
+ parse_raw_index(raw_index)
51
52
  end
52
53
 
53
54
  # Remove the index from the collection
@@ -58,7 +59,22 @@ module Ashikawa
58
59
  # index = Ashikawa::Core::Index.new(collection, raw_index)
59
60
  # index.delete
60
61
  def delete
61
- @collection.send_request("index/#{@collection.id}/#{@id}", :delete => {})
62
+ @collection.send_request("index/#{@id}", :delete => {})
63
+ end
64
+
65
+ private
66
+
67
+ # Parse information returned from the server
68
+ #
69
+ # @param [Hash] raw_index
70
+ # @return self
71
+ # @api private
72
+ def parse_raw_index(raw_index)
73
+ @id = raw_index["id"]
74
+ @on = raw_index["fields"].map { |field| field.to_sym } if raw_index.has_key?("fields")
75
+ @type = raw_index["type"].to_sym if raw_index.has_key?("type")
76
+ @unique = raw_index["unique"]
77
+ self
62
78
  end
63
79
  end
64
80
  end
@@ -1,9 +1,9 @@
1
1
  require 'ashikawa-core/cursor'
2
2
  require 'ashikawa-core/document'
3
3
  require 'ashikawa-core/exceptions/no_collection_provided'
4
+ require 'ashikawa-core/exceptions/client_error/bad_syntax'
4
5
  require 'forwardable'
5
6
  require 'backports'
6
- require 'rest-client'
7
7
 
8
8
  module Ashikawa
9
9
  module Core
@@ -38,7 +38,7 @@ module Ashikawa
38
38
  # query = Ashikawa::Core::Query.new(collection)
39
39
  # query.all # => #<Cursor id=33>
40
40
  def all(options={})
41
- simple_query_request("/simple/all",
41
+ simple_query_request("simple/all",
42
42
  options,
43
43
  [:limit, :skip])
44
44
  end
@@ -56,7 +56,7 @@ module Ashikawa
56
56
  # query = Ashikawa::Core::Query.new(collection)
57
57
  # query.by_example({ "color" => "red" }, :options => { :limit => 1 }) #=> #<Cursor id=2444>
58
58
  def by_example(example={}, options={})
59
- simple_query_request("/simple/by-example",
59
+ simple_query_request("simple/by-example",
60
60
  { :example => example }.merge(options),
61
61
  [:limit, :skip, :example])
62
62
  end
@@ -71,7 +71,7 @@ module Ashikawa
71
71
  # query = Ashikawa::Core::Query.new(collection)
72
72
  # query.first_example({ "color" => "red"}) # => #<Document id=2444 color="red">
73
73
  def first_example(example = {})
74
- response = simple_query_request("/simple/first-example",
74
+ response = simple_query_request("simple/first-example",
75
75
  { :example => example },
76
76
  [:example])
77
77
  response.first
@@ -92,7 +92,7 @@ module Ashikawa
92
92
  # query = Ashikawa::Core::Query.new(collection)
93
93
  # query.near(:latitude => 37.331693, :longitude => -122.030468)
94
94
  def near(options={})
95
- simple_query_request("/simple/near",
95
+ simple_query_request("simple/near",
96
96
  options,
97
97
  [:latitude, :longitude, :distance, :skip, :limit, :geo])
98
98
  end
@@ -113,7 +113,7 @@ module Ashikawa
113
113
  # query = Ashikawa::Core::Query.new(collection)
114
114
  # query.within(:latitude => 37.331693, :longitude => -122.030468, :radius => 100)
115
115
  def within(options={})
116
- simple_query_request("/simple/within",
116
+ simple_query_request("simple/within",
117
117
  options,
118
118
  [:latitude, :longitude, :radius, :distance, :skip, :limit, :geo])
119
119
  end
@@ -133,7 +133,7 @@ module Ashikawa
133
133
  # query = Ashikawa::Core::Query.new(collection)
134
134
  # query.within(:latitude => 37.331693, :longitude => -122.030468, :radius => 100)
135
135
  def in_range(options={})
136
- simple_query_request("/simple/range",
136
+ simple_query_request("simple/range",
137
137
  options,
138
138
  [:attribute, :left, :right, :closed, :limit, :skip])
139
139
  end
@@ -149,7 +149,7 @@ module Ashikawa
149
149
  # query = Ashikawa::Core::Query.new(collection)
150
150
  # query.execute("FOR u IN users LIMIT 2") # => #<Cursor id=33>
151
151
  def execute(query, options = {})
152
- post_request("/cursor",
152
+ post_request("cursor",
153
153
  options.merge({ :query => query }),
154
154
  [:query, :count, :batch_size])
155
155
  end
@@ -163,8 +163,8 @@ module Ashikawa
163
163
  # query = Ashikawa::Core::Query.new(collection)
164
164
  # query.valid?("FOR u IN users LIMIT 2") # => true
165
165
  def valid?(query)
166
- !!post_request("/query", { :query => query })
167
- rescue RestClient::BadRequest
166
+ !!post_request("query", { :query => query })
167
+ rescue Ashikawa::Core::BadSyntax
168
168
  false
169
169
  end
170
170