ashikawa-core 0.8.0 → 0.9.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +49 -0
- data/Gemfile +3 -2
- data/Gemfile.devtools +14 -22
- data/Guardfile +3 -2
- data/README.md +37 -6
- data/Rakefile +2 -1
- data/ashikawa-core.gemspec +2 -2
- data/cache/Mac_applications +1 -0
- data/config/devtools.yml +5 -0
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -2
- data/config/reek.yml +1 -1
- data/config/rubocop.yml +23 -25
- data/lib/ashikawa-core.rb +6 -5
- data/lib/ashikawa-core/collection.rb +142 -165
- data/lib/ashikawa-core/configuration.rb +41 -2
- data/lib/ashikawa-core/connection.rb +17 -16
- data/lib/ashikawa-core/cursor.rb +18 -12
- data/lib/ashikawa-core/database.rb +69 -59
- data/lib/ashikawa-core/document.rb +22 -20
- data/lib/ashikawa-core/edge.rb +8 -6
- data/lib/ashikawa-core/exceptions/client_error.rb +1 -0
- data/lib/ashikawa-core/exceptions/client_error/authentication_failed.rb +25 -0
- data/lib/ashikawa-core/exceptions/client_error/bad_syntax.rb +3 -2
- data/lib/ashikawa-core/exceptions/client_error/resource_not_found.rb +3 -2
- data/lib/ashikawa-core/exceptions/client_error/resource_not_found/collection_not_found.rb +3 -2
- data/lib/ashikawa-core/exceptions/client_error/resource_not_found/document_not_found.rb +3 -2
- data/lib/ashikawa-core/exceptions/client_error/resource_not_found/index_not_found.rb +3 -2
- data/lib/ashikawa-core/exceptions/no_collection_provided.rb +1 -0
- data/lib/ashikawa-core/exceptions/server_error.rb +1 -0
- data/lib/ashikawa-core/exceptions/server_error/json_error.rb +3 -2
- data/lib/ashikawa-core/figure.rb +18 -17
- data/lib/ashikawa-core/index.rb +15 -5
- data/lib/ashikawa-core/key_options.rb +5 -4
- data/lib/ashikawa-core/query.rb +38 -27
- data/lib/ashikawa-core/request_preprocessor.rb +4 -3
- data/lib/ashikawa-core/response_preprocessor.rb +64 -24
- data/lib/ashikawa-core/status.rb +1 -0
- data/lib/ashikawa-core/transaction.rb +12 -11
- data/lib/ashikawa-core/version.rb +2 -1
- data/spec/acceptance/basic_spec.rb +117 -116
- data/spec/acceptance/index_spec.rb +18 -15
- data/spec/acceptance/query_spec.rb +61 -64
- data/spec/acceptance/spec_helper.rb +26 -3
- data/spec/acceptance/transactions_spec.rb +12 -16
- data/spec/setup/arangodb.sh +2 -2
- data/spec/unit/collection_spec.rb +224 -242
- data/spec/unit/configuration_spec.rb +64 -0
- data/spec/unit/connection_spec.rb +121 -111
- data/spec/unit/cursor_spec.rb +78 -65
- data/spec/unit/database_spec.rb +112 -163
- data/spec/unit/document_spec.rb +74 -70
- data/spec/unit/edge_spec.rb +45 -33
- data/spec/unit/exception_spec.rb +28 -38
- data/spec/unit/figure_spec.rb +44 -47
- data/spec/unit/index_spec.rb +27 -24
- data/spec/unit/key_options_spec.rb +19 -17
- data/spec/unit/query_spec.rb +186 -135
- data/spec/unit/spec_helper.rb +14 -3
- data/spec/unit/status_spec.rb +37 -37
- data/spec/unit/transaction_spec.rb +71 -74
- data/tasks/adjustments.rake +10 -34
- metadata +11 -13
- data/spec/acceptance/arango_helper.rb +0 -27
- data/spec/acceptance_auth/arango_helper.rb +0 -30
- data/spec/acceptance_auth/auth_spec.rb +0 -40
- data/spec/acceptance_auth/spec_helper.rb +0 -6
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
module Ashikawa
|
2
3
|
module Core
|
3
4
|
# Options for controlling keys of a collection
|
@@ -44,10 +45,10 @@ module Ashikawa
|
|
44
45
|
# @example Create a new KeyOptions object
|
45
46
|
# KeyOptions.new({ :type => :autoincrement })
|
46
47
|
def initialize(raw_key_options)
|
47
|
-
@type = raw_key_options[
|
48
|
-
@offset = raw_key_options[
|
49
|
-
@increment = raw_key_options[
|
50
|
-
@allow_user_keys = raw_key_options[
|
48
|
+
@type = raw_key_options['type']
|
49
|
+
@offset = raw_key_options['offset']
|
50
|
+
@increment = raw_key_options['increment']
|
51
|
+
@allow_user_keys = raw_key_options['allowUserKeys']
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
data/lib/ashikawa-core/query.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'ashikawa-core/cursor'
|
2
3
|
require 'ashikawa-core/document'
|
3
4
|
require 'ashikawa-core/exceptions/no_collection_provided'
|
@@ -11,14 +12,14 @@ module Ashikawa
|
|
11
12
|
extend Forwardable
|
12
13
|
|
13
14
|
ALLOWED_KEYS_FOR_PATH = {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
'simple/all' => [:limit, :skip, :collection],
|
16
|
+
'simple/by-example' => [:limit, :skip, :example, :collection],
|
17
|
+
'simple/near' => [:latitude, :longitude, :distance, :skip, :limit, :geo, :collection],
|
18
|
+
'simple/within' => [:latitude, :longitude, :radius, :distance, :skip, :limit, :geo, :collection],
|
19
|
+
'simple/range' => [:attribute, :left, :right, :closed, :limit, :skip, :collection],
|
20
|
+
'cursor' => [:query, :count, :batch_size, :collection],
|
21
|
+
'query' => [:query],
|
22
|
+
'simple/first-example' => [:example, :collection]
|
22
23
|
}
|
23
24
|
|
24
25
|
# Delegate sending requests to the connection
|
@@ -48,7 +49,7 @@ module Ashikawa
|
|
48
49
|
# query = Ashikawa::Core::Query.new(collection)
|
49
50
|
# query.all # => #<Cursor id=33>
|
50
51
|
def all(options = {})
|
51
|
-
simple_query_request(
|
52
|
+
simple_query_request('simple/all', options)
|
52
53
|
end
|
53
54
|
|
54
55
|
# Looks for documents in a collection which match the given criteria
|
@@ -62,9 +63,9 @@ module Ashikawa
|
|
62
63
|
# @api public
|
63
64
|
# @example Find all documents in a collection that are red
|
64
65
|
# query = Ashikawa::Core::Query.new(collection)
|
65
|
-
# query.by_example({
|
66
|
+
# query.by_example({ 'color' => 'red' }, :options => { :limit => 1 }) #=> #<Cursor id=2444>
|
66
67
|
def by_example(example = {}, options = {})
|
67
|
-
simple_query_request(
|
68
|
+
simple_query_request('simple/by-example', { example: example }.merge(options))
|
68
69
|
end
|
69
70
|
|
70
71
|
# Looks for one document in a collection which matches the given criteria
|
@@ -75,11 +76,11 @@ module Ashikawa
|
|
75
76
|
# @api public
|
76
77
|
# @example Find one document in a collection that is red
|
77
78
|
# query = Ashikawa::Core::Query.new(collection)
|
78
|
-
# query.first_example({
|
79
|
+
# query.first_example({ 'color' => 'red'}) # => #<Document id=2444 color="red">
|
79
80
|
def first_example(example = {})
|
80
|
-
request = prepare_request(
|
81
|
-
response = send_request(
|
82
|
-
Document.new(database, response[
|
81
|
+
request = prepare_request('simple/first-example', { example: example, collection: collection.name })
|
82
|
+
response = send_request('simple/first-example', { put: request })
|
83
|
+
Document.new(database, response['document'])
|
83
84
|
end
|
84
85
|
|
85
86
|
# Looks for documents in a collection based on location
|
@@ -97,7 +98,7 @@ module Ashikawa
|
|
97
98
|
# query = Ashikawa::Core::Query.new(collection)
|
98
99
|
# query.near(:latitude => 37.331693, :longitude => -122.030468)
|
99
100
|
def near(options = {})
|
100
|
-
simple_query_request(
|
101
|
+
simple_query_request('simple/near', options)
|
101
102
|
end
|
102
103
|
|
103
104
|
# Looks for documents in a collection within a radius
|
@@ -116,7 +117,7 @@ module Ashikawa
|
|
116
117
|
# query = Ashikawa::Core::Query.new(collection)
|
117
118
|
# query.within(:latitude => 37.331693, :longitude => -122.030468, :radius => 100)
|
118
119
|
def within(options = {})
|
119
|
-
simple_query_request(
|
120
|
+
simple_query_request('simple/within', options)
|
120
121
|
end
|
121
122
|
|
122
123
|
# Looks for documents in a collection with an attribute between two values
|
@@ -124,7 +125,7 @@ module Ashikawa
|
|
124
125
|
# @option options [Integer] :attribute The attribute path to check.
|
125
126
|
# @option options [Integer] :left The lower bound
|
126
127
|
# @option options [Integer] :right The upper bound
|
127
|
-
# @option options [Integer] :closed If true,
|
128
|
+
# @option options [Integer] :closed If true, the interval includes right
|
128
129
|
# @option options [Integer] :skip The documents to skip in the query (optional).
|
129
130
|
# @option options [Integer] :limit The maximal amount of documents to return (optional).
|
130
131
|
# @return [Cursor]
|
@@ -134,7 +135,7 @@ module Ashikawa
|
|
134
135
|
# query = Ashikawa::Core::Query.new(collection)
|
135
136
|
# query.within(:latitude => 37.331693, :longitude => -122.030468, :radius => 100)
|
136
137
|
def in_range(options = {})
|
137
|
-
simple_query_request(
|
138
|
+
simple_query_request('simple/range', options)
|
138
139
|
end
|
139
140
|
|
140
141
|
# Send an AQL query to the database
|
@@ -146,9 +147,9 @@ module Ashikawa
|
|
146
147
|
# @api public
|
147
148
|
# @example Send an AQL query to the database
|
148
149
|
# query = Ashikawa::Core::Query.new(collection)
|
149
|
-
# query.execute(
|
150
|
+
# query.execute('FOR u IN users LIMIT 2') # => #<Cursor id=33>
|
150
151
|
def execute(query, options = {})
|
151
|
-
wrapped_request(
|
152
|
+
wrapped_request('cursor', :post, options.merge({ query: query }))
|
152
153
|
end
|
153
154
|
|
154
155
|
# Test if an AQL query is valid
|
@@ -158,9 +159,9 @@ module Ashikawa
|
|
158
159
|
# @api public
|
159
160
|
# @example Validate an AQL query
|
160
161
|
# query = Ashikawa::Core::Query.new(collection)
|
161
|
-
# query.valid?(
|
162
|
+
# query.valid?('FOR u IN users LIMIT 2') # => true
|
162
163
|
def valid?(query)
|
163
|
-
!!wrapped_request(
|
164
|
+
!!wrapped_request('query', :post, { query: query })
|
164
165
|
rescue Ashikawa::Core::BadSyntax
|
165
166
|
false
|
166
167
|
end
|
@@ -193,9 +194,19 @@ module Ashikawa
|
|
193
194
|
def prepare_request(path, options)
|
194
195
|
allowed_keys = ALLOWED_KEYS_FOR_PATH.fetch(path)
|
195
196
|
options.keep_if { |key, _| allowed_keys.include?(key) }
|
196
|
-
|
197
|
-
[key.to_s
|
198
|
-
|
197
|
+
options.reduce({}) { |result, (key, value)|
|
198
|
+
result[snake_to_camel_case(key.to_s)] = value
|
199
|
+
result
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
# Translates Snake Case to Camel Case
|
204
|
+
#
|
205
|
+
# @param [String] str
|
206
|
+
# @return [String] The translated String
|
207
|
+
# @api private
|
208
|
+
def snake_to_camel_case(str)
|
209
|
+
str.gsub(/_(.)/) { |match| match[1].upcase }
|
199
210
|
end
|
200
211
|
|
201
212
|
# Send a simple query to the server
|
@@ -207,7 +218,7 @@ module Ashikawa
|
|
207
218
|
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
208
219
|
# @api private
|
209
220
|
def simple_query_request(path, request)
|
210
|
-
wrapped_request(path, :put, request.merge({ :
|
221
|
+
wrapped_request(path, :put, request.merge({ collection: collection.name }))
|
211
222
|
end
|
212
223
|
|
213
224
|
# Perform a wrapped request
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'faraday'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
module Ashikawa
|
5
6
|
module Core
|
@@ -44,6 +45,6 @@ module Ashikawa
|
|
44
45
|
end
|
45
46
|
|
46
47
|
Faraday.register_middleware :request,
|
47
|
-
|
48
|
+
ashikawa_request: -> { RequestPreprocessor}
|
48
49
|
end
|
49
50
|
end
|
@@ -1,22 +1,25 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'faraday'
|
3
|
+
require 'json'
|
4
|
+
require 'ashikawa-core/exceptions/client_error'
|
5
|
+
require 'ashikawa-core/exceptions/client_error/resource_not_found'
|
6
|
+
require 'ashikawa-core/exceptions/client_error/resource_not_found/index_not_found'
|
7
|
+
require 'ashikawa-core/exceptions/client_error/resource_not_found/document_not_found'
|
8
|
+
require 'ashikawa-core/exceptions/client_error/resource_not_found/collection_not_found'
|
9
|
+
require 'ashikawa-core/exceptions/client_error/bad_syntax'
|
10
|
+
require 'ashikawa-core/exceptions/client_error/authentication_failed'
|
11
|
+
require 'ashikawa-core/exceptions/server_error'
|
12
|
+
require 'ashikawa-core/exceptions/server_error/json_error'
|
11
13
|
|
12
14
|
module Ashikawa
|
13
15
|
module Core
|
14
16
|
# Preprocessor for Faraday Requests
|
15
17
|
class ResponsePreprocessor < Faraday::Middleware
|
16
|
-
ClientErrorStatuses = 400...499
|
17
|
-
ServerErrorStatuses = 500...599
|
18
18
|
BadSyntaxStatus = 400
|
19
|
-
|
19
|
+
AuthenticationFailed = 401
|
20
|
+
ResourceNotFoundError = 404
|
21
|
+
ClientErrorStatuses = 405...499
|
22
|
+
ServerErrorStatuses = 500...599
|
20
23
|
|
21
24
|
# Create a new Response Preprocessor
|
22
25
|
#
|
@@ -51,20 +54,56 @@ module Ashikawa
|
|
51
54
|
# @api private
|
52
55
|
def resource_not_found_for(env)
|
53
56
|
raise case env[:url].path
|
54
|
-
when
|
55
|
-
when
|
56
|
-
when
|
57
|
+
when %r{\A(/_db/[^/]+)?/_api/document} then Ashikawa::Core::DocumentNotFoundException
|
58
|
+
when %r{\A(/_db/[^/]+)?/_api/collection} then Ashikawa::Core::CollectionNotFoundException
|
59
|
+
when %r{\A(/_db/[^/]+)?/_api/index} then Ashikawa::Core::IndexNotFoundException
|
57
60
|
else Ashikawa::Core::ResourceNotFound
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|
64
|
+
# Raise a Bad Syntax Error
|
65
|
+
#
|
66
|
+
# @raise [BadSyntax]
|
67
|
+
# @return nil
|
68
|
+
# @api private
|
69
|
+
def bad_syntax
|
70
|
+
raise Ashikawa::Core::BadSyntax
|
71
|
+
end
|
72
|
+
|
73
|
+
# Raise an Authentication Failed Error
|
74
|
+
#
|
75
|
+
# @raise [AuthenticationFailed]
|
76
|
+
# @return nil
|
77
|
+
# @api private
|
78
|
+
def authentication_failed
|
79
|
+
raise Ashikawa::Core::AuthenticationFailed
|
80
|
+
end
|
81
|
+
|
82
|
+
# Raise a Client Error for a given body
|
83
|
+
#
|
84
|
+
# @raise [ClientError]
|
85
|
+
# @return nil
|
86
|
+
# @api private
|
87
|
+
def client_error_status_for(body)
|
88
|
+
raise Ashikawa::Core::ClientError, error(body)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Raise a Server Error for a given body
|
92
|
+
#
|
93
|
+
# @raise [ServerError]
|
94
|
+
# @return nil
|
95
|
+
# @api private
|
96
|
+
def server_error_status_for(body)
|
97
|
+
raise Ashikawa::Core::ServerError, error(body)
|
98
|
+
end
|
99
|
+
|
61
100
|
# Parse the JSON
|
62
101
|
#
|
63
102
|
# @param [Hash] env Environment info
|
64
103
|
# @return [Hash] The parsed body
|
65
104
|
# @api private
|
66
105
|
def parse_json(env)
|
67
|
-
|
106
|
+
fail JSON::ParserError unless json_content_type?(env[:response_headers]['content-type'])
|
68
107
|
JSON.parse(env[:body])
|
69
108
|
rescue JSON::ParserError
|
70
109
|
raise Ashikawa::Core::JsonError
|
@@ -76,7 +115,7 @@ module Ashikawa
|
|
76
115
|
# @return [Boolean]
|
77
116
|
# @api private
|
78
117
|
def json_content_type?(content_type)
|
79
|
-
content_type ==
|
118
|
+
content_type == 'application/json; charset=utf-8'
|
80
119
|
end
|
81
120
|
|
82
121
|
# Handle the status code
|
@@ -86,10 +125,11 @@ module Ashikawa
|
|
86
125
|
# @api private
|
87
126
|
def handle_status(env)
|
88
127
|
case env[:status]
|
89
|
-
when BadSyntaxStatus then
|
90
|
-
when
|
91
|
-
when
|
92
|
-
when
|
128
|
+
when BadSyntaxStatus then bad_syntax
|
129
|
+
when AuthenticationFailed then authentication_failed
|
130
|
+
when ResourceNotFoundError then resource_not_found_for(env)
|
131
|
+
when ClientErrorStatuses then client_error_status_for(env[:body])
|
132
|
+
when ServerErrorStatuses then server_error_status_for(env[:body])
|
93
133
|
end
|
94
134
|
end
|
95
135
|
|
@@ -110,11 +150,11 @@ module Ashikawa
|
|
110
150
|
# @api private
|
111
151
|
def error(body)
|
112
152
|
parsed_body = JSON.parse(body)
|
113
|
-
"#{parsed_body[
|
153
|
+
"#{parsed_body['errorNum']}: #{parsed_body["errorMessage"]}"
|
114
154
|
end
|
115
155
|
end
|
116
156
|
|
117
157
|
Faraday.register_middleware :response,
|
118
|
-
|
158
|
+
ashikawa_response: -> { ResponsePreprocessor}
|
119
159
|
end
|
120
160
|
end
|
data/lib/ashikawa-core/status.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
module Ashikawa
|
2
3
|
module Core
|
3
4
|
# A JavaScript Transaction on the database
|
@@ -7,7 +8,7 @@ module Ashikawa
|
|
7
8
|
# @return [Array<String>]
|
8
9
|
# @api public
|
9
10
|
# @example Get the collections that the transaction writes to
|
10
|
-
# transaction.write_collections # => [
|
11
|
+
# transaction.write_collections # => ['collection_1']
|
11
12
|
def write_collections
|
12
13
|
@request_parameters[:collections][:write]
|
13
14
|
end
|
@@ -17,7 +18,7 @@ module Ashikawa
|
|
17
18
|
# @return [Array<String>]
|
18
19
|
# @api public
|
19
20
|
# @example Get the collections that the transaction reads from
|
20
|
-
# transaction.read_collections # => [
|
21
|
+
# transaction.read_collections # => ['collection_1']
|
21
22
|
def read_collections
|
22
23
|
@request_parameters[:collections][:read]
|
23
24
|
end
|
@@ -70,14 +71,14 @@ module Ashikawa
|
|
70
71
|
# @option options [Array<String>] :read The collections you want to read from
|
71
72
|
# @api public
|
72
73
|
# @example Create a Transaction
|
73
|
-
# transaction = Ashikawa::Core::Transaction.new(database,
|
74
|
-
# :read => [
|
74
|
+
# transaction = Ashikawa::Core::Transaction.new(database, 'function () { return 5; }',
|
75
|
+
# :read => ['collection_1']
|
75
76
|
def initialize(database, action, options)
|
76
77
|
@database = database
|
77
78
|
@request_parameters = {
|
78
|
-
:
|
79
|
-
:
|
80
|
-
:
|
79
|
+
action: action,
|
80
|
+
collections: parse_options(options),
|
81
|
+
waitForSync: false
|
81
82
|
}
|
82
83
|
end
|
83
84
|
|
@@ -90,8 +91,8 @@ module Ashikawa
|
|
90
91
|
# transaction.execute({ :a => 5 })
|
91
92
|
def execute(action_parameters = :no_params_provided)
|
92
93
|
@request_parameters[:params] = action_parameters unless action_parameters == :no_params_provided
|
93
|
-
response = @database.send_request(
|
94
|
-
response[
|
94
|
+
response = @database.send_request('transaction', post: @request_parameters)
|
95
|
+
response['result']
|
95
96
|
end
|
96
97
|
|
97
98
|
private
|
@@ -104,8 +105,8 @@ module Ashikawa
|
|
104
105
|
# @api private
|
105
106
|
def parse_options(options)
|
106
107
|
collections = {}
|
107
|
-
collections[:write] = options[:write] if options.
|
108
|
-
collections[:read] = options[:read] if options.
|
108
|
+
collections[:write] = options[:write] if options.key? :write
|
109
|
+
collections[:read] = options[:read] if options.key? :read
|
109
110
|
collections
|
110
111
|
end
|
111
112
|
end
|
@@ -1,174 +1,175 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'acceptance/spec_helper'
|
2
3
|
|
3
|
-
describe
|
4
|
-
describe
|
5
|
-
subject {
|
6
|
-
Ashikawa::Core::Database.new do |config|
|
7
|
-
config.url = ARANGO_HOST
|
8
|
-
end
|
9
|
-
}
|
4
|
+
describe 'Basics' do
|
5
|
+
describe 'for an initialized database' do
|
6
|
+
subject { DATABASE }
|
10
7
|
|
11
8
|
after :each do
|
12
9
|
subject.collections.each { |collection| collection.delete }
|
13
10
|
end
|
14
11
|
|
15
|
-
it
|
16
|
-
subject[
|
17
|
-
subject[
|
18
|
-
subject[
|
12
|
+
it 'should do what the README describes' do
|
13
|
+
subject['my_collection']
|
14
|
+
subject['my_collection'].name = 'new_name'
|
15
|
+
subject['new_name'].delete
|
19
16
|
end
|
20
17
|
|
21
|
-
it
|
18
|
+
it 'should create and delete collections' do
|
22
19
|
subject.collections.each { |collection| collection.delete }
|
23
|
-
subject[
|
24
|
-
subject[
|
25
|
-
subject[
|
26
|
-
subject.collections.length.
|
27
|
-
subject[
|
28
|
-
subject.collections.length.
|
20
|
+
subject['collection_1']
|
21
|
+
subject['collection_2']
|
22
|
+
subject['collection_3']
|
23
|
+
expect(subject.collections.length).to eq(3)
|
24
|
+
subject['collection_3'].delete
|
25
|
+
expect(subject.collections.length).to eq(2)
|
29
26
|
end
|
30
27
|
|
31
|
-
it
|
32
|
-
subject.create_collection(
|
33
|
-
subject[
|
28
|
+
it 'should create a non-volatile collection by default' do
|
29
|
+
subject.create_collection('nonvolatile_collection')
|
30
|
+
expect(subject['nonvolatile_collection'].volatile?).to be_false
|
34
31
|
end
|
35
32
|
|
36
|
-
it
|
37
|
-
subject.create_collection(
|
38
|
-
subject[
|
33
|
+
it 'should create a volatile collection' do
|
34
|
+
subject.create_collection('volatile_collection', is_volatile: true)
|
35
|
+
expect(subject['volatile_collection'].volatile?).to be_true
|
39
36
|
end
|
40
37
|
|
41
|
-
it
|
42
|
-
subject.create_collection(
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
38
|
+
it 'should create an autoincrementing collection' do
|
39
|
+
subject.create_collection('autoincrement_collection', is_volatile: true, key_options: {
|
40
|
+
type: :autoincrement,
|
41
|
+
increment: 10,
|
42
|
+
allow_user_keys: false
|
46
43
|
})
|
47
|
-
key_options = subject[
|
44
|
+
key_options = subject['autoincrement_collection'].key_options
|
48
45
|
|
49
|
-
key_options.type.
|
50
|
-
key_options.offset.
|
51
|
-
key_options.increment.
|
52
|
-
key_options.allow_user_keys.
|
46
|
+
expect(key_options.type).to eq('autoincrement')
|
47
|
+
expect(key_options.offset).to eq(0)
|
48
|
+
expect(key_options.increment).to eq(10)
|
49
|
+
expect(key_options.allow_user_keys).to eq(false)
|
53
50
|
end
|
54
51
|
|
55
|
-
it
|
56
|
-
subject.create_collection(
|
57
|
-
subject[
|
52
|
+
it 'should be possible to create an edge collection' do
|
53
|
+
subject.create_collection('edge_collection', content_type: :edge)
|
54
|
+
expect(subject['edge_collection'].content_type).to eq(:edge)
|
58
55
|
end
|
59
56
|
|
60
|
-
it
|
61
|
-
my_collection = subject[
|
62
|
-
my_collection.name.
|
63
|
-
my_collection.name =
|
64
|
-
my_collection.name.
|
57
|
+
it 'should be possible to change the name of a collection' do
|
58
|
+
my_collection = subject['test_collection']
|
59
|
+
expect(my_collection.name).to eq('test_collection')
|
60
|
+
my_collection.name = 'my_new_name'
|
61
|
+
expect(my_collection.name).to eq('my_new_name')
|
65
62
|
end
|
66
63
|
|
67
|
-
it
|
68
|
-
my_collection = subject[
|
69
|
-
subject[my_collection.id].name.
|
64
|
+
it 'should be possible to find a collection by ID' do
|
65
|
+
my_collection = subject['test_collection']
|
66
|
+
expect(subject[my_collection.id].name).to eq('test_collection')
|
70
67
|
end
|
71
68
|
|
72
|
-
it
|
73
|
-
subject.system_collections.length.
|
69
|
+
it 'should be possible to list all system collections' do
|
70
|
+
expect(subject.system_collections.length).to be > 0
|
74
71
|
end
|
75
72
|
|
76
|
-
it
|
77
|
-
my_collection = subject[
|
78
|
-
my_collection.status.loaded
|
73
|
+
it 'should be possible to load and unload collections' do
|
74
|
+
my_collection = subject['test_collection']
|
75
|
+
expect(my_collection.status.loaded?).to be_true
|
79
76
|
my_collection.unload
|
80
77
|
my_id = my_collection.id
|
81
|
-
|
82
|
-
subject[my_id].status.loaded
|
83
|
-
end
|
84
|
-
|
85
|
-
it
|
86
|
-
my_collection = subject[
|
87
|
-
my_collection.figure.alive_size.class.
|
88
|
-
my_collection.figure.alive_count.class.
|
89
|
-
my_collection.figure.dead_size.class.
|
90
|
-
my_collection.figure.dead_count.class.
|
91
|
-
my_collection.figure.dead_deletion.class.
|
92
|
-
my_collection.figure.datafiles_count.class.
|
93
|
-
my_collection.figure.datafiles_file_size.class.
|
94
|
-
my_collection.figure.journals_count.class.
|
95
|
-
my_collection.figure.journals_file_size.class.
|
96
|
-
my_collection.figure.shapes_count.class.
|
97
|
-
end
|
98
|
-
|
99
|
-
it
|
100
|
-
my_collection = subject[
|
78
|
+
subject[my_id]
|
79
|
+
expect(subject[my_id].status.loaded?).to be_false
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should be possible to get figures' do
|
83
|
+
my_collection = subject['test_collection']
|
84
|
+
expect(my_collection.figure.alive_size.class).to eq(Fixnum)
|
85
|
+
expect(my_collection.figure.alive_count.class).to eq(Fixnum)
|
86
|
+
expect(my_collection.figure.dead_size.class).to eq(Fixnum)
|
87
|
+
expect(my_collection.figure.dead_count.class).to eq(Fixnum)
|
88
|
+
expect(my_collection.figure.dead_deletion.class).to eq(Fixnum)
|
89
|
+
expect(my_collection.figure.datafiles_count.class).to eq(Fixnum)
|
90
|
+
expect(my_collection.figure.datafiles_file_size.class).to eq(Fixnum)
|
91
|
+
expect(my_collection.figure.journals_count.class).to eq(Fixnum)
|
92
|
+
expect(my_collection.figure.journals_file_size.class).to eq(Fixnum)
|
93
|
+
expect(my_collection.figure.shapes_count.class).to eq(Fixnum)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should change and receive information about waiting for sync' do
|
97
|
+
my_collection = subject['my_collection']
|
101
98
|
my_collection.wait_for_sync = false
|
102
|
-
my_collection.wait_for_sync
|
99
|
+
expect(my_collection.wait_for_sync?).to be_false
|
103
100
|
my_collection.wait_for_sync = true
|
104
|
-
my_collection.wait_for_sync
|
101
|
+
expect(my_collection.wait_for_sync?).to be_true
|
105
102
|
end
|
106
103
|
|
107
|
-
it
|
108
|
-
empty_collection = subject[
|
109
|
-
empty_collection.length.
|
110
|
-
empty_collection.create_document(
|
111
|
-
empty_collection.create_document(
|
112
|
-
empty_collection.length.
|
104
|
+
it 'should be possible to get information about the number of documents' do
|
105
|
+
empty_collection = subject['empty_collection']
|
106
|
+
expect(empty_collection.length).to eq(0)
|
107
|
+
empty_collection.create_document(name: 'testname', age: 27)
|
108
|
+
empty_collection.create_document(name: 'anderer name', age: 28)
|
109
|
+
expect(empty_collection.length).to eq(2)
|
113
110
|
empty_collection.truncate!
|
114
|
-
empty_collection.length.
|
111
|
+
expect(empty_collection.length).to eq(0)
|
115
112
|
end
|
116
113
|
|
117
|
-
it
|
118
|
-
collection = subject[
|
114
|
+
it 'should be possible to update the attributes of a document' do
|
115
|
+
collection = subject['documenttests']
|
119
116
|
|
120
|
-
document = collection.create_document(:
|
117
|
+
document = collection.create_document(name: 'The Dude', bowling: true)
|
121
118
|
document_key = document.key
|
122
|
-
document[
|
119
|
+
document['name'] = 'Other Dude'
|
123
120
|
document.save
|
124
121
|
|
125
|
-
collection.fetch(document_key)[
|
122
|
+
expect(collection.fetch(document_key)['name']).to eq('Other Dude')
|
126
123
|
end
|
127
124
|
|
128
|
-
it
|
129
|
-
collection = subject[
|
125
|
+
it 'should be possible to access and create documents from a collection' do
|
126
|
+
collection = subject['documenttests']
|
130
127
|
|
131
|
-
document = collection.create_document(:
|
128
|
+
document = collection.create_document(name: 'The Dude', bowling: true)
|
132
129
|
document_key = document.key
|
133
|
-
collection.fetch(document_key)[
|
130
|
+
expect(collection.fetch(document_key)['name']).to eq('The Dude')
|
134
131
|
|
135
|
-
collection.replace(document_key, { :
|
136
|
-
collection.fetch(document_key)[
|
132
|
+
collection.replace(document_key, { name: 'Other Dude', bowling: true })
|
133
|
+
expect(collection.fetch(document_key)['name']).to eq('Other Dude')
|
137
134
|
end
|
138
135
|
|
139
|
-
it
|
140
|
-
nodes = subject.create_collection(
|
141
|
-
edges = subject.create_collection(
|
136
|
+
it 'should be possible to create an edge between two documents' do
|
137
|
+
nodes = subject.create_collection('nodecollection')
|
138
|
+
edges = subject.create_collection('edgecollection', content_type: :edge)
|
142
139
|
|
143
|
-
a = nodes.create_document(
|
144
|
-
b = nodes.create_document(
|
145
|
-
e = edges.create_edge(a, b, {:
|
140
|
+
a = nodes.create_document(name: 'a')
|
141
|
+
b = nodes.create_document(name: 'b')
|
142
|
+
e = edges.create_edge(a, b, { name: 'fance_edge' })
|
146
143
|
|
147
144
|
e = edges.fetch(e.key)
|
148
|
-
e.from_id.
|
149
|
-
e.to_id.
|
145
|
+
expect(e.from_id).to eq(a.id)
|
146
|
+
expect(e.to_id).to eq(b.id)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should be possible to get a single attribute by AQL query' do
|
150
|
+
collection = subject['documenttests']
|
151
|
+
collection.truncate!
|
152
|
+
collection.create_document(name: 'The Dude', bowling: true)
|
153
|
+
|
154
|
+
expect(subject.query.execute('FOR doc IN documenttests RETURN doc.name').to_a.first). to eq 'The Dude'
|
150
155
|
end
|
151
156
|
end
|
152
157
|
|
153
|
-
describe
|
154
|
-
let(:database) {
|
155
|
-
|
156
|
-
|
157
|
-
end
|
158
|
-
}
|
159
|
-
let(:collection) { database["documenttests"] }
|
160
|
-
subject { collection.create_document(:name => "The Dude") }
|
158
|
+
describe 'for a created document' do
|
159
|
+
let(:database) { DATABASE }
|
160
|
+
let(:collection) { database['documenttests'] }
|
161
|
+
subject { collection.create_document(name: 'The Dude') }
|
161
162
|
let(:document_key) { subject.key }
|
162
163
|
|
163
|
-
it
|
164
|
-
subject[
|
165
|
-
subject[
|
166
|
-
collection.fetch(document_key)[
|
164
|
+
it 'should be possible to manipulate documents and save them' do
|
165
|
+
subject['name'] = 'Jeffrey Lebowski'
|
166
|
+
expect(subject['name']).to eq('Jeffrey Lebowski')
|
167
|
+
expect(collection.fetch(document_key)['name']).to eq('The Dude')
|
167
168
|
subject.save
|
168
|
-
collection.fetch(document_key)[
|
169
|
+
expect(collection.fetch(document_key)['name']).to eq('Jeffrey Lebowski')
|
169
170
|
end
|
170
171
|
|
171
|
-
it
|
172
|
+
it 'should be possible to delete a document' do
|
172
173
|
collection.fetch(document_key).delete
|
173
174
|
expect {
|
174
175
|
collection.fetch(document_key)
|
@@ -181,14 +182,14 @@ describe "Basics" do
|
|
181
182
|
}.to raise_exception Ashikawa::Core::DocumentNotFoundException
|
182
183
|
end
|
183
184
|
|
184
|
-
it
|
185
|
+
it 'should be possible to refresh a document' do
|
185
186
|
changed_document = collection.fetch(document_key)
|
186
|
-
changed_document[
|
187
|
+
changed_document['name'] = 'New Name'
|
187
188
|
changed_document.save
|
188
189
|
|
189
|
-
subject[
|
190
|
+
expect(subject['name']).to eq('The Dude')
|
190
191
|
subject.refresh!
|
191
|
-
subject[
|
192
|
+
expect(subject['name']).to eq('New Name')
|
192
193
|
end
|
193
194
|
end
|
194
195
|
end
|