ashikawa-core 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|