arangodb-odm 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -1
- data/Gemfile.lock +5 -2
- data/README.md +20 -0
- data/Rakefile +1 -7
- data/VERSION +1 -1
- data/lib/arangodb-odm.rb +33 -1
- data/lib/collections.rb +24 -0
- data/lib/indices.rb +26 -0
- data/lib/queries.rb +58 -2
- data/test/example_document.rb +2 -1
- data/test/helper.rb +5 -0
- data/test/test_collections.rb +8 -0
- data/test/test_indices.rb +7 -0
- data/test/test_queries.rb +20 -0
- metadata +13 -23
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -25,7 +25,6 @@ GEM
|
|
25
25
|
multi_json (1.4.0)
|
26
26
|
multi_xml (0.5.1)
|
27
27
|
rake (10.0.2)
|
28
|
-
rcov (1.0.0)
|
29
28
|
rdoc (2.4.3)
|
30
29
|
hoe (>= 1.12.1)
|
31
30
|
minitest (~> 1.3)
|
@@ -36,6 +35,10 @@ GEM
|
|
36
35
|
shoulda-matchers (1.4.2)
|
37
36
|
activesupport (>= 3.0.0)
|
38
37
|
bourne (~> 1.1.2)
|
38
|
+
simplecov (0.7.1)
|
39
|
+
multi_json (~> 1.0)
|
40
|
+
simplecov-html (~> 0.7.1)
|
41
|
+
simplecov-html (0.7.1)
|
39
42
|
|
40
43
|
PLATFORMS
|
41
44
|
ruby
|
@@ -45,6 +48,6 @@ DEPENDENCIES
|
|
45
48
|
httparty
|
46
49
|
jeweler (~> 1.6.4)
|
47
50
|
json
|
48
|
-
rcov
|
49
51
|
rdoc (~> 2.4.2)
|
50
52
|
shoulda
|
53
|
+
simplecov
|
data/README.md
CHANGED
@@ -57,6 +57,12 @@
|
|
57
57
|
#### First by example
|
58
58
|
|
59
59
|
ExampleDocument.where('foo' => 'bar', 'a' => 'b').first
|
60
|
+
|
61
|
+
#### Range
|
62
|
+
|
63
|
+
# Make sure you've setup a skip-list index on the attribute
|
64
|
+
ExampleDocument.attribute('test').left(0).right(100).all
|
65
|
+
ExampleDocument.attribute('test').left(0).right(100).closed(true).skip(10).limit(10).all
|
60
66
|
|
61
67
|
## Callbacks
|
62
68
|
|
@@ -98,6 +104,20 @@
|
|
98
104
|
|
99
105
|
def change_something_else; end
|
100
106
|
end
|
107
|
+
|
108
|
+
## Indices
|
109
|
+
|
110
|
+
### Skip List Index Definition
|
111
|
+
|
112
|
+
class ExampleDocument < ArangoDb::Base
|
113
|
+
collection :examples
|
114
|
+
skiplist :test, :something_else
|
115
|
+
end
|
116
|
+
|
117
|
+
### Creating indices
|
118
|
+
|
119
|
+
# Creates all indices defined in the document. Run it once when you setup your document model...
|
120
|
+
ExampleDocument.ensure_indices
|
101
121
|
|
102
122
|
## Copyright
|
103
123
|
|
data/Rakefile
CHANGED
@@ -33,13 +33,7 @@ Rake::TestTask.new(:test) do |test|
|
|
33
33
|
test.verbose = true
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
Rcov::RcovTask.new do |test|
|
38
|
-
test.libs << 'test'
|
39
|
-
test.pattern = 'test/**/test_*.rb'
|
40
|
-
test.verbose = true
|
41
|
-
test.rcov_opts << '--exclude "gems/*"'
|
42
|
-
end
|
36
|
+
# TODO simplecov
|
43
37
|
|
44
38
|
task :default => :test
|
45
39
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/lib/arangodb-odm.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
require "httparty"
|
3
3
|
require "json"
|
4
|
+
|
5
|
+
require "collections"
|
4
6
|
require "queries"
|
7
|
+
require "indices"
|
5
8
|
|
6
9
|
module ArangoDb
|
7
10
|
class Transport
|
@@ -29,60 +32,83 @@ module ArangoDb
|
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
35
|
+
class Index
|
36
|
+
attr_accessor :indices
|
37
|
+
|
38
|
+
def initialize(indices)
|
39
|
+
@indices = indices
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
32
43
|
module Properties
|
33
44
|
def self.included(klass)
|
34
45
|
klass.extend ClassMethods
|
35
46
|
end
|
36
47
|
|
37
48
|
module ClassMethods
|
49
|
+
# The collection to use for this document.
|
38
50
|
def collection(value)
|
39
51
|
(class << self; self; end).send(:define_method, 'collection') do
|
40
52
|
value.to_s
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
56
|
+
def skiplist(*fields)
|
57
|
+
(class << self; self; end).send(:define_method, 'skiplist') do
|
58
|
+
fields.to_a
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets the transport class to use. Defaults to httparty.
|
44
63
|
def transport(value)
|
45
64
|
(class << self; self; end).send(:define_method, 'transport') do
|
46
65
|
value
|
47
66
|
end
|
48
67
|
end
|
49
68
|
|
69
|
+
# Sets the document value proxy to use.
|
50
70
|
def target(value)
|
51
71
|
(class << self; self; end).send(:define_method, 'target') do
|
52
72
|
value
|
53
73
|
end
|
54
74
|
end
|
55
75
|
|
76
|
+
# Callback that is being invoked before a document is first created.
|
56
77
|
def before_create(value)
|
57
78
|
self.send(:define_method, 'before_create') do
|
58
79
|
value
|
59
80
|
end
|
60
81
|
end
|
61
82
|
|
83
|
+
# Callback that is being invoked after a document is first created.
|
62
84
|
def after_create(value)
|
63
85
|
self.send(:define_method, 'after_create') do
|
64
86
|
value
|
65
87
|
end
|
66
88
|
end
|
67
89
|
|
90
|
+
# Callback that is being invoked before a document is updated.
|
68
91
|
def before_save(value)
|
69
92
|
self.send(:define_method, 'before_save') do
|
70
93
|
value
|
71
94
|
end
|
72
95
|
end
|
73
96
|
|
97
|
+
# Callback that is being invoked after a document was updated.
|
74
98
|
def after_save(value)
|
75
99
|
self.send(:define_method, 'after_save') do
|
76
100
|
value
|
77
101
|
end
|
78
102
|
end
|
79
103
|
|
104
|
+
# Callback that is being invoked before a document is destroyed.
|
80
105
|
def before_destroy(value)
|
81
106
|
self.send(:define_method, 'before_destroy') do
|
82
107
|
value
|
83
108
|
end
|
84
109
|
end
|
85
110
|
|
111
|
+
# Callback that is being invoked after a document was destroyed.
|
86
112
|
def after_destroy(value)
|
87
113
|
self.send(:define_method, 'after_destroy') do
|
88
114
|
value
|
@@ -106,18 +132,24 @@ module ArangoDb
|
|
106
132
|
#
|
107
133
|
# class ExampleDocument < ArangoDb::Base
|
108
134
|
# collection :examples
|
135
|
+
# skiplist [:a, :b]
|
109
136
|
# end
|
110
137
|
class Base
|
111
138
|
include ArangoDb::Properties
|
139
|
+
extend ArangoDb::Collections::ClassMethods
|
112
140
|
extend ArangoDb::Queries::ClassMethods
|
141
|
+
extend ArangoDb::Indices::ClassMethods
|
113
142
|
transport ArangoDb::Transport
|
114
143
|
target ArangoDb::Document
|
115
144
|
db_attrs []
|
116
|
-
attr_reader :target
|
145
|
+
attr_reader :target, :index
|
117
146
|
|
118
147
|
def initialize
|
119
148
|
@transport = self.class.transport
|
120
149
|
@target = self.class.target.new(self.class.collection, self.class.db_attributes)
|
150
|
+
if self.class.respond_to?(:skiplist) and self.class.skiplist
|
151
|
+
@index = ArangoDb::Index.new(:skiplist => self.class.skiplist)
|
152
|
+
end
|
121
153
|
end
|
122
154
|
|
123
155
|
def self.find(document_handle)
|
data/lib/collections.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module ArangoDb
|
2
|
+
module Collections
|
3
|
+
module ClassMethods
|
4
|
+
# POST /_api/collection
|
5
|
+
# Creates an new collection with a given name. The request must contain an object with the following attributes.
|
6
|
+
# name: The name of the collection.
|
7
|
+
# waitForSync (optional, default: false): If true then the data is synchronised to disk before returning from a create or update of an document.
|
8
|
+
# journalSize (optional, default is a configuration parameter): The maximal size of a journal or datafile. Note that this also limits the maximal
|
9
|
+
# size of a single object. Must be at least 1MB.
|
10
|
+
# isSystem (optional, default is false): If true, create a system collection. In this case collection-name should start with an underscore.
|
11
|
+
# End users should normally create non-system collections only.
|
12
|
+
# API implementors may be required to create system collections in very special occasions, but normally a regular collection will do.
|
13
|
+
# type (optional, default is 2): the type of the collection to create. The following values for type are valid:
|
14
|
+
# 2: document collections
|
15
|
+
# 3: edge collection
|
16
|
+
def create_collection(options = {})
|
17
|
+
res = transport.post("/_api/collection", :body => options.merge('name' => collection).to_json)
|
18
|
+
if res.parsed_response and not res.parsed_response["code"] == 200
|
19
|
+
res.parsed_response["id"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/indices.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module ArangoDb
|
2
|
+
module Indices
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
# POST /_api/index?collection=collection-identifier
|
6
|
+
# Creates a skip-list index for the collection collection-identifier, if it does not already exist. The call expects an object
|
7
|
+
# containing the index details.
|
8
|
+
# type: must be equal to "skiplist".
|
9
|
+
# fields: A list of attribute paths.
|
10
|
+
# unique: If true, then create a unique index.
|
11
|
+
def create_skiplist(fields)
|
12
|
+
query_parameters = { "type" => "skiplist", "unique" => false, "fields" => fields }
|
13
|
+
endpoint = "/_api/index?collection=#{collection}"
|
14
|
+
res = transport.post(endpoint, :body => query_parameters.to_json)
|
15
|
+
if res.parsed_response and not (res.parsed_response["code"] == 200 or res.parsed_response["code"] == 201)
|
16
|
+
raise "Couldn't create skip list index: #{res.parsed_response["code"]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ensure_indices
|
21
|
+
create_skiplist(skiplist) if skiplist
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/queries.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module ArangoDb
|
2
2
|
module Queries
|
3
3
|
class QueryResult < Array
|
4
|
+
# TODO
|
4
5
|
end
|
5
6
|
|
6
7
|
class Query
|
@@ -24,6 +25,26 @@ module ArangoDb
|
|
24
25
|
self
|
25
26
|
end
|
26
27
|
|
28
|
+
def attribute(attr_name)
|
29
|
+
@attribute = attr_name
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def left(number)
|
34
|
+
@left = number
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def right(number)
|
39
|
+
@right = number
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def closed(boolean)
|
44
|
+
@closed = boolean
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
27
48
|
def first
|
28
49
|
@model.first(query_parameters)
|
29
50
|
end
|
@@ -31,13 +52,17 @@ module ArangoDb
|
|
31
52
|
def all
|
32
53
|
@model.all(query_parameters)
|
33
54
|
end
|
34
|
-
|
55
|
+
|
35
56
|
private
|
36
57
|
def query_parameters
|
37
58
|
options = {}
|
38
59
|
options['limit'] = @limit if @limit
|
39
60
|
options['skip'] = @skip if @skip
|
40
61
|
options['example'] = @where if @where
|
62
|
+
options['left'] = @left if @left
|
63
|
+
options['right'] = @right if @right
|
64
|
+
options['attribute'] = @attribute if @attribute
|
65
|
+
options['closed'] = @closed if @closed
|
41
66
|
options
|
42
67
|
end
|
43
68
|
end
|
@@ -56,9 +81,24 @@ module ArangoDb
|
|
56
81
|
# example: The example.
|
57
82
|
# skip: The documents to skip in the query. (optional)
|
58
83
|
# limit: The maximal amount of documents to return. (optional)
|
84
|
+
#
|
85
|
+
# PUT /_api/simple/range
|
86
|
+
# This will find all documents within a given range. You must declare a skip-list index on the attribute in order
|
87
|
+
# to be able to use a range query.The call expects a JSON hash array as body with the following attributes:
|
88
|
+
# collection: The identifier or name of the collection to query.
|
89
|
+
# attribute: The attribute path to check.
|
90
|
+
# left: The lower bound.
|
91
|
+
# right: The upper bound.
|
92
|
+
# closed: If true, use interval including left and right, otherwise exclude right, but include left.
|
93
|
+
# skip: The documents to skip in the query. (optional)
|
94
|
+
# limit: The maximal amount of documents to return. (optional)
|
59
95
|
def all(options = {})
|
60
96
|
query_parameters = {'collection' => collection}; endpoint = '/_api/simple/all'
|
61
|
-
|
97
|
+
if options and options['example'] and options['example'].any?
|
98
|
+
endpoint = '/_api/simple/by-example'
|
99
|
+
elsif options and options['left'] and options['right'] and options['attribute']
|
100
|
+
endpoint = '/_api/simple/range'
|
101
|
+
end
|
62
102
|
res = transport.put(endpoint, :body => query_parameters.merge(options).to_json)
|
63
103
|
if res.code == 201 and res.parsed_response and res.parsed_response["result"]
|
64
104
|
query_result = QueryResult.new
|
@@ -91,6 +131,22 @@ module ArangoDb
|
|
91
131
|
def skip(number)
|
92
132
|
Query.new(self).skip(number)
|
93
133
|
end
|
134
|
+
|
135
|
+
def attribute(attr_name)
|
136
|
+
Query.new(self).attribute(attr_name)
|
137
|
+
end
|
138
|
+
|
139
|
+
def left(number)
|
140
|
+
Query.new(self).left(number)
|
141
|
+
end
|
142
|
+
|
143
|
+
def right(number)
|
144
|
+
Query.new(self).right(number)
|
145
|
+
end
|
146
|
+
|
147
|
+
def closed(boolean)
|
148
|
+
Query.new(self).closed(boolean)
|
149
|
+
end
|
94
150
|
end
|
95
151
|
end
|
96
152
|
end
|
data/test/example_document.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -19,5 +19,10 @@ require 'another_example_document.rb'
|
|
19
19
|
# Set your ArangoDB host...
|
20
20
|
ArangoDb::Transport.base_uri 'http://localhost:8529'
|
21
21
|
|
22
|
+
# Initial setup
|
23
|
+
ExampleDocument.create_collection # only needed to be able to create indices on the initial test run
|
24
|
+
ExampleDocument.ensure_indices
|
25
|
+
# AnotherExampleDocument.create_collection
|
26
|
+
|
22
27
|
class Test::Unit::TestCase
|
23
28
|
end
|
data/test/test_queries.rb
CHANGED
@@ -29,4 +29,24 @@ class TestArangoDbQueries < Test::Unit::TestCase
|
|
29
29
|
example_document = ExampleDocument.where(:something => 'not existant').first
|
30
30
|
assert_nil example_document
|
31
31
|
end
|
32
|
+
|
33
|
+
should "get documents in a given range" do
|
34
|
+
ts = Time.now.to_i + rand(1000); count = 10
|
35
|
+
count.times {|i| ExampleDocument.create(:foo => "1", :test => ts + i)}
|
36
|
+
|
37
|
+
example_documents = ExampleDocument.attribute(:test).left(ts + 6).right(ts + 9).all
|
38
|
+
assert_not_nil example_documents
|
39
|
+
assert_equal example_documents.size, 3
|
40
|
+
assert_equal example_documents[0].test, ts + 6
|
41
|
+
assert_equal example_documents[1].test, ts + 7
|
42
|
+
assert_equal example_documents[2].test, ts + 8
|
43
|
+
|
44
|
+
example_documents = ExampleDocument.attribute(:test).left(ts + 6).right(ts + 9).closed(true).all
|
45
|
+
assert_not_nil example_documents
|
46
|
+
assert_equal example_documents.size, 4
|
47
|
+
assert_equal example_documents[0].test, ts + 6
|
48
|
+
assert_equal example_documents[1].test, ts + 7
|
49
|
+
assert_equal example_documents[2].test, ts + 8
|
50
|
+
assert_equal example_documents[3].test, ts + 9
|
51
|
+
end
|
32
52
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arangodb-odm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 1
|
10
|
+
version: 0.3.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Oliver Kiessler
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-12-
|
18
|
+
date: 2012-12-08 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -93,20 +93,6 @@ dependencies:
|
|
93
93
|
type: :development
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
requirement: &id006 !ruby/object:Gem::Requirement
|
96
|
-
none: false
|
97
|
-
requirements:
|
98
|
-
- - ">="
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
hash: 3
|
101
|
-
segments:
|
102
|
-
- 0
|
103
|
-
version: "0"
|
104
|
-
version_requirements: *id006
|
105
|
-
name: rcov
|
106
|
-
prerelease: false
|
107
|
-
type: :development
|
108
|
-
- !ruby/object:Gem::Dependency
|
109
|
-
requirement: &id007 !ruby/object:Gem::Requirement
|
110
96
|
none: false
|
111
97
|
requirements:
|
112
98
|
- - ~>
|
@@ -117,12 +103,12 @@ dependencies:
|
|
117
103
|
- 4
|
118
104
|
- 2
|
119
105
|
version: 2.4.2
|
120
|
-
version_requirements: *
|
106
|
+
version_requirements: *id006
|
121
107
|
name: rdoc
|
122
108
|
prerelease: false
|
123
109
|
type: :development
|
124
110
|
- !ruby/object:Gem::Dependency
|
125
|
-
requirement: &
|
111
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
126
112
|
none: false
|
127
113
|
requirements:
|
128
114
|
- - ">="
|
@@ -131,12 +117,12 @@ dependencies:
|
|
131
117
|
segments:
|
132
118
|
- 0
|
133
119
|
version: "0"
|
134
|
-
version_requirements: *
|
120
|
+
version_requirements: *id007
|
135
121
|
name: httparty
|
136
122
|
prerelease: false
|
137
123
|
type: :runtime
|
138
124
|
- !ruby/object:Gem::Dependency
|
139
|
-
requirement: &
|
125
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
140
126
|
none: false
|
141
127
|
requirements:
|
142
128
|
- - ">="
|
@@ -145,7 +131,7 @@ dependencies:
|
|
145
131
|
segments:
|
146
132
|
- 0
|
147
133
|
version: "0"
|
148
|
-
version_requirements: *
|
134
|
+
version_requirements: *id008
|
149
135
|
name: json
|
150
136
|
prerelease: false
|
151
137
|
type: :runtime
|
@@ -167,11 +153,15 @@ files:
|
|
167
153
|
- Rakefile
|
168
154
|
- VERSION
|
169
155
|
- lib/arangodb-odm.rb
|
156
|
+
- lib/collections.rb
|
157
|
+
- lib/indices.rb
|
170
158
|
- lib/queries.rb
|
171
159
|
- test/another_example_document.rb
|
172
160
|
- test/example_document.rb
|
173
161
|
- test/helper.rb
|
174
162
|
- test/test_arangodb-odm.rb
|
163
|
+
- test/test_collections.rb
|
164
|
+
- test/test_indices.rb
|
175
165
|
- test/test_queries.rb
|
176
166
|
homepage: http://github.com/okiess/arangodb-odm
|
177
167
|
licenses:
|