ashikawa-core 0.4.1 → 0.5.1
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.
- data/.gitignore +2 -0
- data/.travis.yml +2 -0
- data/CONTRIBUTING.md +5 -8
- data/Guardfile +1 -1
- data/README.md +15 -1
- data/Rakefile +45 -12
- data/ashikawa-core.gemspec +13 -6
- data/lib/ashikawa-core/collection.rb +24 -160
- data/lib/ashikawa-core/connection.rb +64 -38
- data/lib/ashikawa-core/cursor.rb +15 -9
- data/lib/ashikawa-core/database.rb +5 -12
- data/lib/ashikawa-core/document.rb +13 -10
- data/lib/ashikawa-core/exceptions/document_not_found.rb +4 -1
- data/lib/ashikawa-core/exceptions/no_collection_provided.rb +11 -0
- data/lib/ashikawa-core/index.rb +6 -6
- data/lib/ashikawa-core/query.rb +251 -0
- data/lib/ashikawa-core/version.rb +1 -1
- data/spec/{integration → acceptance}/arango_helper.rb +1 -1
- data/spec/{integration → acceptance}/basic_spec.rb +4 -4
- data/spec/{integration → acceptance}/index_spec.rb +1 -1
- data/spec/acceptance/query_spec.rb +90 -0
- data/spec/{integration → acceptance}/spec_helper.rb +0 -0
- data/spec/{integration_auth → acceptance_auth}/arango_helper.rb +1 -1
- data/spec/{integration_auth → acceptance_auth}/auth_spec.rb +1 -1
- data/spec/{integration_auth → acceptance_auth}/spec_helper.rb +0 -0
- data/spec/fixtures/query/valid.json +5 -0
- data/spec/setup/arangodb.sh +68 -0
- data/spec/unit/collection_spec.rb +43 -143
- data/spec/unit/database_spec.rb +10 -14
- data/spec/unit/exception_spec.rb +14 -0
- data/spec/unit/query_spec.rb +215 -0
- data/spec/unit/spec_helper.rb +7 -1
- metadata +107 -30
- data/spec/integration/query_spec.rb +0 -78
@@ -29,16 +29,19 @@ module Ashikawa
|
|
29
29
|
# @api public
|
30
30
|
def initialize(database, raw_document)
|
31
31
|
@database = database
|
32
|
-
@
|
33
|
-
|
34
|
-
if @is_persistent
|
35
|
-
@collection_id, @id = raw_document['_id'].split('/').map { |id| id.to_i }
|
36
|
-
@revision = raw_document['_rev'].to_i
|
37
|
-
end
|
38
|
-
|
32
|
+
@collection_id, @id = raw_document['_id'].split('/').map { |id| id.to_i } unless raw_document['_id'].nil?
|
33
|
+
@revision = raw_document['_rev'].to_i unless raw_document['_rev'].nil?
|
39
34
|
@content = raw_document.delete_if { |key, value| key[0] == "_" }
|
40
35
|
end
|
41
36
|
|
37
|
+
# Raises an exception if the document is not persisted
|
38
|
+
#
|
39
|
+
# @raise [DocumentNotFoundException]
|
40
|
+
# @api semi-public
|
41
|
+
def check_if_persisted!
|
42
|
+
raise DocumentNotFoundException if @id.nil?
|
43
|
+
end
|
44
|
+
|
42
45
|
# Get the value of an attribute of the document
|
43
46
|
#
|
44
47
|
# @param [String] attribute_name
|
@@ -52,7 +55,7 @@ module Ashikawa
|
|
52
55
|
#
|
53
56
|
# @api public
|
54
57
|
def delete
|
55
|
-
|
58
|
+
check_if_persisted!
|
56
59
|
@database.send_request "document/#{@collection_id}/#{@id}", delete: {}
|
57
60
|
end
|
58
61
|
|
@@ -62,7 +65,7 @@ module Ashikawa
|
|
62
65
|
# @param [Object] value
|
63
66
|
# @api public
|
64
67
|
def []=(attribute_name, value)
|
65
|
-
|
68
|
+
check_if_persisted!
|
66
69
|
@content[attribute_name] = value
|
67
70
|
end
|
68
71
|
|
@@ -78,7 +81,7 @@ module Ashikawa
|
|
78
81
|
#
|
79
82
|
# @api public
|
80
83
|
def save()
|
81
|
-
|
84
|
+
check_if_persisted!
|
82
85
|
@database.send_request "document/#{@collection_id}/#{@id}", put: @content
|
83
86
|
end
|
84
87
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module Ashikawa
|
2
2
|
module Core
|
3
|
-
# This Exception is thrown
|
3
|
+
# This Exception is thrown when a document was requested from
|
4
4
|
# the server that does not exist.
|
5
5
|
class DocumentNotFoundException < RuntimeError
|
6
|
+
def to_s
|
7
|
+
"You requested a document from the server that does not exist"
|
8
|
+
end
|
6
9
|
end
|
7
10
|
end
|
8
11
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Ashikawa
|
2
|
+
module Core
|
3
|
+
# This Exception is thrown when a Query object should execute a simple query
|
4
|
+
# but no collection was provided upon creation
|
5
|
+
class NoCollectionProvidedException < RuntimeError
|
6
|
+
def to_s
|
7
|
+
"A simple query can't be executed by a Query object without a collection"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/ashikawa-core/index.rb
CHANGED
@@ -25,15 +25,15 @@ module Ashikawa
|
|
25
25
|
# Create a new Index
|
26
26
|
#
|
27
27
|
# @param [Collection] collection The collection the index is defined on
|
28
|
-
# @param [Hash]
|
28
|
+
# @param [Hash] raw_index The JSON representation of the index
|
29
29
|
# @return [Index]
|
30
30
|
# @api
|
31
|
-
def initialize(collection,
|
31
|
+
def initialize(collection, raw_index)
|
32
32
|
@collection = collection
|
33
|
-
@id =
|
34
|
-
@on =
|
35
|
-
@type =
|
36
|
-
@unique =
|
33
|
+
@id = raw_index["id"].split("/")[1].to_i if raw_index.has_key? "id"
|
34
|
+
@on = raw_index["fields"].map { |field| field.to_sym } if raw_index.has_key? "fields"
|
35
|
+
@type = raw_index["type"].to_sym if raw_index.has_key? "type"
|
36
|
+
@unique = raw_index["unique"] if raw_index.has_key? "unique"
|
37
37
|
end
|
38
38
|
|
39
39
|
# Remove the index from the collection
|
@@ -0,0 +1,251 @@
|
|
1
|
+
require 'ashikawa-core/cursor'
|
2
|
+
require 'ashikawa-core/document'
|
3
|
+
require 'ashikawa-core/exceptions/no_collection_provided'
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
module Ashikawa
|
7
|
+
module Core
|
8
|
+
# Formulate a Query on a collection or on a database
|
9
|
+
class Query
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
# Delegate sending requests to the connection
|
13
|
+
delegate send_request: :@connection
|
14
|
+
|
15
|
+
# Initializes a Query
|
16
|
+
#
|
17
|
+
# @param [Collection, Database] connection
|
18
|
+
# @return [Query]
|
19
|
+
def initialize(connection)
|
20
|
+
@connection = connection
|
21
|
+
end
|
22
|
+
|
23
|
+
# Retrieves all documents for a collection
|
24
|
+
#
|
25
|
+
# @note It is advised to NOT use this method due to possible HUGE data amounts requested
|
26
|
+
# @option options [Integer] :limit limit the maximum number of queried and returned elements.
|
27
|
+
# @option options [Integer] :skip skip the first <n> documents of the query.
|
28
|
+
# @return [Cursor]
|
29
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
30
|
+
# @api public
|
31
|
+
# @example Get an array with all documents
|
32
|
+
# query = Ashikawa::Core::Query.new collection
|
33
|
+
# query.all # => #<Cursor id=33>
|
34
|
+
def all(options={})
|
35
|
+
simple_query_request "/simple/all",
|
36
|
+
options,
|
37
|
+
[:limit, :skip]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Looks for documents in a collection which match the given criteria
|
41
|
+
#
|
42
|
+
# @option example [Hash] a Hash with data matching the documents you are looking for.
|
43
|
+
# @option options [Hash] a Hash with additional settings for the query.
|
44
|
+
# @option options [Integer] :limit limit the maximum number of queried and returned elements.
|
45
|
+
# @option options [Integer] :skip skip the first <n> documents of the query.
|
46
|
+
# @return [Cursor]
|
47
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
48
|
+
# @api public
|
49
|
+
# @example Find all documents in a collection that are red
|
50
|
+
# query = Ashikawa::Core::Query.new collection
|
51
|
+
# query.by_example { "color" => "red" }, :options => { :limit => 1 } # => #<Cursor id=2444>
|
52
|
+
def by_example(example={}, options={})
|
53
|
+
simple_query_request "/simple/by-example",
|
54
|
+
{ example: example }.merge(options),
|
55
|
+
[:limit, :skip, :example]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Looks for one document in a collection which matches the given criteria
|
59
|
+
#
|
60
|
+
# @param [Hash] example a Hash with data matching the document you are looking for.
|
61
|
+
# @return [Document]
|
62
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
63
|
+
# @api public
|
64
|
+
# @example Find one document in a collection that is red
|
65
|
+
# query = Ashikawa::Core::Query.new collection
|
66
|
+
# query.first_example { "color" => "red"} # => #<Document id=2444 color="red">
|
67
|
+
def first_example(example = {})
|
68
|
+
response = simple_query_request "/simple/first-example",
|
69
|
+
{ example: example },
|
70
|
+
[:example]
|
71
|
+
response.first
|
72
|
+
end
|
73
|
+
|
74
|
+
# Looks for documents in a collection based on location
|
75
|
+
#
|
76
|
+
# @option options [Integer] :latitude Latitude location for your search.
|
77
|
+
# @option options [Integer] :longitude Longitude location for your search.
|
78
|
+
# @option options [Integer] :skip The documents to skip in the query.
|
79
|
+
# @option options [Integer] :distance If given, the attribute key used to store the distance.
|
80
|
+
# @option options [Integer] :limit The maximal amount of documents to return (default: 100).
|
81
|
+
# @option options [Integer] :geo If given, the identifier of the geo-index to use.
|
82
|
+
# @return [Cursor]
|
83
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
84
|
+
# @api public
|
85
|
+
# @example Find all documents at Infinite Loop
|
86
|
+
# query = Ashikawa::Core::Query.new collection
|
87
|
+
# query.near latitude: 37.331693, longitude: -122.030468
|
88
|
+
def near(options={})
|
89
|
+
simple_query_request "/simple/near",
|
90
|
+
options,
|
91
|
+
[:latitude, :longitude, :distance, :skip, :limit, :geo]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Looks for documents in a collection within a radius
|
95
|
+
#
|
96
|
+
# @option options [Integer] :latitude Latitude location for your search.
|
97
|
+
# @option options [Integer] :longitude Longitude location for your search.
|
98
|
+
# @option options [Integer] :radius Radius around the given location you want to search in.
|
99
|
+
# @option options [Integer] :skip The documents to skip in the query.
|
100
|
+
# @option options [Integer] :distance If given, the attribute key used to store the distance.
|
101
|
+
# @option options [Integer] :limit The maximal amount of documents to return (default: 100).
|
102
|
+
# @option options [Integer] :geo If given, the identifier of the geo-index to use.
|
103
|
+
# @return [Cursor]
|
104
|
+
# @api public
|
105
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
106
|
+
# @example Find all documents within a radius of 100 to Infinite Loop
|
107
|
+
# query = Ashikawa::Core::Query.new collection
|
108
|
+
# query.within latitude: 37.331693, longitude: -122.030468, radius: 100
|
109
|
+
def within(options={})
|
110
|
+
simple_query_request "/simple/within",
|
111
|
+
options,
|
112
|
+
[:latitude, :longitude, :radius, :distance, :skip, :limit, :geo]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Looks for documents in a collection with an attribute between two values
|
116
|
+
#
|
117
|
+
# @option options [Integer] :attribute The attribute path to check.
|
118
|
+
# @option options [Integer] :left The lower bound
|
119
|
+
# @option options [Integer] :right The upper bound
|
120
|
+
# @option options [Integer] :closed If true, use intervall including left and right, otherwise exclude right, but include left.
|
121
|
+
# @option options [Integer] :skip The documents to skip in the query (optional).
|
122
|
+
# @option options [Integer] :limit The maximal amount of documents to return (optional).
|
123
|
+
# @return [Cursor]
|
124
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
125
|
+
# @api public
|
126
|
+
# @example Find all documents within a radius of 100 to Infinite Loop
|
127
|
+
# query = Ashikawa::Core::Query.new collection
|
128
|
+
# query.within latitude: 37.331693, longitude: -122.030468, radius: 100
|
129
|
+
def in_range(options={})
|
130
|
+
simple_query_request "/simple/range",
|
131
|
+
options,
|
132
|
+
[:attribute, :left, :right, :closed, :limit, :skip]
|
133
|
+
end
|
134
|
+
|
135
|
+
# Send an AQL query to the database
|
136
|
+
#
|
137
|
+
# @param [String] query
|
138
|
+
# @option options [Integer] :count Should the number of results be counted?
|
139
|
+
# @option options [Integer] :batch_size Set the number of results returned at once
|
140
|
+
# @return [Cursor]
|
141
|
+
# @api public
|
142
|
+
# @example Send an AQL query to the database
|
143
|
+
# query = Ashikawa::Core::Query.new collection
|
144
|
+
# query.execute "FOR u IN users LIMIT 2" # => #<Cursor id=33>
|
145
|
+
def execute(query, options = {})
|
146
|
+
post_request "/cursor",
|
147
|
+
options.merge({ query: query }),
|
148
|
+
[:query, :count, :batch_size]
|
149
|
+
end
|
150
|
+
|
151
|
+
# Test if an AQL query is valid
|
152
|
+
#
|
153
|
+
# @param [String] query
|
154
|
+
# @return [Boolean]
|
155
|
+
# @api public
|
156
|
+
# @example Validate an AQL query
|
157
|
+
# query = Ashikawa::Core::Query.new collection
|
158
|
+
# query.valid? "FOR u IN users LIMIT 2" # => true
|
159
|
+
def valid?(query)
|
160
|
+
begin
|
161
|
+
!!post_request("/query", { query: query })
|
162
|
+
rescue RestClient::BadRequest
|
163
|
+
false
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# The database object
|
170
|
+
#
|
171
|
+
# @return [Database]
|
172
|
+
# @api private
|
173
|
+
def database
|
174
|
+
@connection.respond_to?(:database) ? @connection.database : @connection
|
175
|
+
end
|
176
|
+
|
177
|
+
# The collection object
|
178
|
+
#
|
179
|
+
# @return [collection]
|
180
|
+
# @api private
|
181
|
+
def collection
|
182
|
+
raise NoCollectionProvidedException unless @connection.respond_to? :database
|
183
|
+
@connection
|
184
|
+
end
|
185
|
+
|
186
|
+
# Removes the keys that are not allowed from an object
|
187
|
+
#
|
188
|
+
# @param [Hash] options
|
189
|
+
# @param [Array<Symbol>] allowed_keys
|
190
|
+
# @return [Hash] The filtered Hash
|
191
|
+
# @api private
|
192
|
+
def allowed_options(options, allowed_keys)
|
193
|
+
options.keep_if { |key, _| allowed_keys.include? key }
|
194
|
+
end
|
195
|
+
|
196
|
+
# Transforms the keys into strings, camelizes them and removes pairs without a value
|
197
|
+
#
|
198
|
+
# @param [Hash] request_data
|
199
|
+
# @return [Hash] Cleaned request data
|
200
|
+
# @api private
|
201
|
+
def prepare_request_data(request_data)
|
202
|
+
Hash[request_data.map { |key, value|
|
203
|
+
[key.to_s.gsub(/_(.)/) { $1.upcase }, value]
|
204
|
+
}].reject { |_, value| value.nil? }
|
205
|
+
end
|
206
|
+
|
207
|
+
# Send a simple query to the server
|
208
|
+
#
|
209
|
+
# @param [String] path The path for the request
|
210
|
+
# @param [Hash] request_data The data send to the database
|
211
|
+
# @param [Array<Symbol>] keys The keys allowed for this request
|
212
|
+
# @return [String] Server response
|
213
|
+
# @raise [NoCollectionProvidedException] If you provided a database, no collection
|
214
|
+
# @api private
|
215
|
+
def simple_query_request(path, request_data, allowed_keys)
|
216
|
+
request_data = request_data.merge({ collection: collection.name })
|
217
|
+
put_request path,
|
218
|
+
request_data,
|
219
|
+
allowed_keys << :collection
|
220
|
+
end
|
221
|
+
|
222
|
+
# Perform a put request
|
223
|
+
#
|
224
|
+
# @param [String] path The path for the request
|
225
|
+
# @param [Hash] request_data The data send to the database
|
226
|
+
# @param [Array] allowed_keys Keys allowed in request_data, if nil: All keys are allowed
|
227
|
+
# @return [Cursor]
|
228
|
+
# @api private
|
229
|
+
def put_request(path, request_data, allowed_keys = nil)
|
230
|
+
request_data = allowed_options request_data, allowed_keys unless allowed_keys.nil?
|
231
|
+
request_data = prepare_request_data request_data
|
232
|
+
server_response = send_request path, :put => request_data
|
233
|
+
Cursor.new database, server_response
|
234
|
+
end
|
235
|
+
|
236
|
+
# Perform a post request
|
237
|
+
#
|
238
|
+
# @param [String] path The path for the request
|
239
|
+
# @param [Hash] request_data The data send to the database
|
240
|
+
# @param [Array] allowed_keys Keys allowed in request_data, if nil: All keys are allowed
|
241
|
+
# @return [Cursor]
|
242
|
+
# @api private
|
243
|
+
def post_request(path, request_data, allowed_keys = nil)
|
244
|
+
request_data = allowed_options request_data, allowed_keys unless allowed_keys.nil?
|
245
|
+
request_data = prepare_request_data request_data
|
246
|
+
server_response = send_request path, :post => request_data
|
247
|
+
Cursor.new database, server_response
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
RSpec.configure do |config|
|
2
2
|
raise "Could not find arangod. Please install it or check if it is in your path." if `which arangod` == ""
|
3
3
|
|
4
|
-
database_directory = "/tmp/ashikawa-
|
4
|
+
database_directory = "/tmp/ashikawa-acceptance"
|
5
5
|
arango_process = false
|
6
6
|
|
7
7
|
config.before(:suite) do
|
@@ -1,11 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'acceptance/spec_helper'
|
2
2
|
|
3
3
|
describe "Basics" do
|
4
4
|
subject { ARANGO_HOST }
|
5
5
|
|
6
|
-
it "should have booted up an ArangoDB instance" do
|
7
|
-
expect { RestClient.get(subject) }.to_not raise_error
|
8
|
-
end
|
6
|
+
# it "should have booted up an ArangoDB instance" do
|
7
|
+
# expect { RestClient.get(subject) }.to_not raise_error
|
8
|
+
# end
|
9
9
|
|
10
10
|
describe "initialized database" do
|
11
11
|
subject { Ashikawa::Core::Database.new ARANGO_HOST }
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'acceptance/spec_helper'
|
2
|
+
|
3
|
+
describe "Queries" do
|
4
|
+
let(:database) { Ashikawa::Core::Database.new ARANGO_HOST }
|
5
|
+
let(:collection) { database["my_collection"] }
|
6
|
+
|
7
|
+
describe "AQL query via the database" do
|
8
|
+
it "should return the documents" do
|
9
|
+
collection << { "name" => "Jeff Lebowski", "bowling" => true }
|
10
|
+
collection << { "name" => "Walter Sobchak", "bowling" => true }
|
11
|
+
collection << { "name" => "Donny Kerabatsos", "bowling" => true }
|
12
|
+
collection << { "name" => "Jeffrey Lebowski", "bowling" => false }
|
13
|
+
|
14
|
+
query = "FOR u IN my_collection FILTER u.bowling == true RETURN u"
|
15
|
+
results = database.query.execute query, batch_size: 2, count: true
|
16
|
+
|
17
|
+
results.length.should == 3
|
18
|
+
results = results.map { |person| person["name"] }
|
19
|
+
results.should include "Jeff Lebowski"
|
20
|
+
results.should_not include "Jeffrey Lebowski"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be possible to validate" do
|
24
|
+
valid_query = "FOR u IN my_collection FILTER u.bowling == true RETURN u"
|
25
|
+
database.query.valid?(valid_query).should be_true
|
26
|
+
|
27
|
+
invalid_query = "FOR u IN my_collection FILTER u.bowling == true"
|
28
|
+
database.query.valid?(invalid_query).should be_false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "simple query via collection object" do
|
33
|
+
subject { collection }
|
34
|
+
before(:each) { subject.truncate! }
|
35
|
+
|
36
|
+
it "should return all documents of a collection" do
|
37
|
+
subject << { name: "testname", age: 27}
|
38
|
+
subject.query.all.first["name"].should == "testname"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be possible to limit and skip results" do
|
42
|
+
subject << { name: "test1"}
|
43
|
+
subject << { name: "test2"}
|
44
|
+
subject << { name: "test3"}
|
45
|
+
|
46
|
+
subject.query.all(limit: 2).length.should == 2
|
47
|
+
subject.query.all(skip: 2).length.should == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be possible to query documents by example" do
|
51
|
+
subject << { "name" => "Random Document" }
|
52
|
+
result = subject.query.by_example name: "Random Document"
|
53
|
+
result.length.should == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "query by geo coordinates" do
|
57
|
+
before :each do
|
58
|
+
subject.add_index :geo, on: [:latitude, :longitude]
|
59
|
+
subject << { "name" => "cologne", "latitude" => 50.948045, "longitude" => 6.961212 }
|
60
|
+
subject << { "name" => "san francisco", "latitude" => -122.395899, "longitude" => 37.793621 }
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be possible to query documents near a certain location" do
|
64
|
+
found_places = subject.query.near latitude: 50, longitude: 6
|
65
|
+
found_places.first["name"].should == "cologne"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should be possible to query documents within a certain range" do
|
69
|
+
found_places = subject.query.within latitude: 50.948040, longitude: 6.961210, radius: 2
|
70
|
+
found_places.length.should == 1
|
71
|
+
found_places.first["name"].should == "cologne"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "queries by integer ranges" do
|
76
|
+
before :each do
|
77
|
+
subject.add_index :skiplist, on: [:age]
|
78
|
+
subject << { "name" => "Georg", "age" => 12 }
|
79
|
+
subject << { "name" => "Anne", "age" => 21 }
|
80
|
+
subject << { "name" => "Jens", "age" => 49 }
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should be possible to query documents for numbers in a certain range" do
|
84
|
+
found_people = subject.query.in_range attribute: "age", left: 20, right: 30, closed: true
|
85
|
+
found_people.length.should == 1
|
86
|
+
found_people.first["name"].should == "Anne"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
RSpec.configure do |config|
|
2
2
|
raise "Could not find arangod. Please install it or check if it is in your path." if `which arangod` == ""
|
3
3
|
|
4
|
-
database_directory = "/tmp/ashikawa-
|
4
|
+
database_directory = "/tmp/ashikawa-acceptance-auth"
|
5
5
|
arango_process = false
|
6
6
|
|
7
7
|
config.before(:suite) do
|
File without changes
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
4
|
+
cd $DIR
|
5
|
+
|
6
|
+
#VERSION=1.0.2
|
7
|
+
VERSION=1.1.beta1
|
8
|
+
|
9
|
+
NAME=ArangoDB-$VERSION
|
10
|
+
|
11
|
+
if [ ! -d "$DIR/$NAME" ]; then
|
12
|
+
# download ArangoDB
|
13
|
+
wget http://www.arangodb.org/travisCI/$NAME.tar.gz
|
14
|
+
tar zxf $NAME.tar.gz
|
15
|
+
fi
|
16
|
+
|
17
|
+
|
18
|
+
PID=$(echo $PPID)
|
19
|
+
TMP_DIR="/tmp/arangodb.$PID"
|
20
|
+
PID_FILE="/tmp/arangodb.$PID.pid"
|
21
|
+
ARANGODB_DIR="$DIR/$NAME"
|
22
|
+
UPDATE_SCRIPT="${ARANGODB_DIR}/js/server/arango-upgrade.js"
|
23
|
+
|
24
|
+
# create database directory
|
25
|
+
mkdir ${TMP_DIR}
|
26
|
+
|
27
|
+
# check for update script
|
28
|
+
echo "looking for: $UPDATE_SCRIPT"
|
29
|
+
if [ -f "$UPDATE_SCRIPT" ] ; then
|
30
|
+
# version 1.1
|
31
|
+
${ARANGODB_DIR}/bin/arangod \
|
32
|
+
--database.directory ${TMP_DIR} \
|
33
|
+
--configuration none \
|
34
|
+
--server.endpoint tcp://127.0.0.1:8529 \
|
35
|
+
--javascript.startup-directory ${ARANGODB_DIR}/js \
|
36
|
+
--javascript.modules-path ${ARANGODB_DIR}/js/server/modules:${ARANGODB_DIR}/js/common/modules \
|
37
|
+
--javascript.script "$UPDATE_SCRIPT"
|
38
|
+
|
39
|
+
${ARANGODB_DIR}/bin/arangod \
|
40
|
+
--database.directory ${TMP_DIR} \
|
41
|
+
--configuration none \
|
42
|
+
--server.endpoint tcp://127.0.0.1:8529 \
|
43
|
+
--javascript.startup-directory ${ARANGODB_DIR}/js \
|
44
|
+
--javascript.modules-path ${ARANGODB_DIR}/js/server/modules:${ARANGODB_DIR}/js/common/modules \
|
45
|
+
--javascript.action-directory ${ARANGODB_DIR}/js/actions/system \
|
46
|
+
--database.maximal-journal-size 1048576 \
|
47
|
+
--server.disable-admin-interface true \
|
48
|
+
--server.disable-authentication true \
|
49
|
+
--javascript.gc-interval 1 &
|
50
|
+
else
|
51
|
+
# version 1.0
|
52
|
+
${ARANGODB_DIR}/bin/arangod ${TMP_DIR} \
|
53
|
+
--configuration none \
|
54
|
+
--pid-file ${PID_FILE} \
|
55
|
+
--javascript.startup-directory ${ARANGODB_DIR}/js \
|
56
|
+
--javascript.modules-path ${ARANGODB_DIR}/js/server/modules:${ARANGODB_DIR}/js/common/modules \
|
57
|
+
--javascript.action-directory ${ARANGODB_DIR}/js/actions/system \
|
58
|
+
--database.maximal-journal-size 1000000 \
|
59
|
+
--javascript.gc-interval 1 &
|
60
|
+
fi
|
61
|
+
|
62
|
+
echo "Waiting until ArangoDB is ready on port 8529"
|
63
|
+
while [[ -z `curl -s 'http://127.0.0.1:8529/_api/version' ` ]] ; do
|
64
|
+
echo -n "."
|
65
|
+
sleep 2s
|
66
|
+
done
|
67
|
+
|
68
|
+
echo "ArangoDB is up"
|