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