active-orient 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/Gemfile +16 -0
- data/Guardfile +21 -0
- data/LICENSE +22 -0
- data/README.md +275 -0
- data/acitve-orient.gemspec +27 -0
- data/config/boot.rb +24 -0
- data/config/connect.yml +13 -0
- data/lib/base.rb +220 -0
- data/lib/base_properties.rb +147 -0
- data/lib/model.rb +441 -0
- data/lib/orient.rb +98 -0
- data/lib/query.rb +88 -0
- data/lib/rest.rb +942 -0
- data/lib/support.rb +315 -0
- data/test.rb +4 -0
- data/usecase.md +91 -0
- metadata +104 -0
data/lib/support.rb
ADDED
@@ -0,0 +1,315 @@
|
|
1
|
+
class String
|
2
|
+
def to_classname
|
3
|
+
if self[0] =='$'
|
4
|
+
self[1..-1]
|
5
|
+
else
|
6
|
+
self.camelize
|
7
|
+
end
|
8
|
+
end
|
9
|
+
def to_orient
|
10
|
+
self.gsub /%/, '(percent)'
|
11
|
+
|
12
|
+
end
|
13
|
+
def rid?
|
14
|
+
self =~ /\A[#]{,1}[0-9]{1,}:[0-9]{1,}\z/
|
15
|
+
end
|
16
|
+
def from_orient
|
17
|
+
if rid?
|
18
|
+
ActiveOrient::Model.autoload_object self
|
19
|
+
else
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class NilClass
|
25
|
+
def to_orient
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
class Symbol
|
30
|
+
def to_orient
|
31
|
+
self.to_s.to_orient
|
32
|
+
end
|
33
|
+
def from_orient
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Numeric
|
39
|
+
def from_orient
|
40
|
+
self
|
41
|
+
end
|
42
|
+
def to_orient
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Time
|
48
|
+
def from_orient
|
49
|
+
self
|
50
|
+
end
|
51
|
+
def to_orient
|
52
|
+
self
|
53
|
+
end
|
54
|
+
end
|
55
|
+
class Date
|
56
|
+
def from_orient
|
57
|
+
self
|
58
|
+
end
|
59
|
+
def to_orient
|
60
|
+
self
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class TrueClass
|
65
|
+
def from_orient
|
66
|
+
self
|
67
|
+
end
|
68
|
+
def to_orient
|
69
|
+
self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
class FalseClass
|
73
|
+
def from_orient
|
74
|
+
self
|
75
|
+
end
|
76
|
+
def to_orient
|
77
|
+
self
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Array
|
82
|
+
def to_orient
|
83
|
+
map &:to_orient
|
84
|
+
end
|
85
|
+
def from_orient
|
86
|
+
map &:from_orient
|
87
|
+
end
|
88
|
+
end
|
89
|
+
class Hash #WithIndifferentAccess
|
90
|
+
def from_orient
|
91
|
+
substitute_hash = HashWithIndifferentAccess.new
|
92
|
+
keys.each{ |k| puts self[k].inspect }
|
93
|
+
keys.each{| k | substitute_hash[k] = self[k].from_orient }
|
94
|
+
substitute_hash
|
95
|
+
|
96
|
+
end
|
97
|
+
def to_orient
|
98
|
+
substitute_hash = Hash.new
|
99
|
+
keys.each{| k | substitute_hash[k] = self[k].to_orient }
|
100
|
+
substitute_hash
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def nested_under_indifferent_access
|
105
|
+
HashWithIndifferentAccess.new self
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
module OrientSupport
|
111
|
+
|
112
|
+
module Support
|
113
|
+
=begin
|
114
|
+
supports
|
115
|
+
|
116
|
+
where: 'string'
|
117
|
+
where: { property: 'value', property: value, ... }
|
118
|
+
where: ['string, { property: value, ... }, ... ]
|
119
|
+
|
120
|
+
|
121
|
+
Used by update and select
|
122
|
+
=end
|
123
|
+
|
124
|
+
def compose_where *arg
|
125
|
+
arg=arg.flatten
|
126
|
+
return "" if arg.blank? || arg.size == 1 && arg.first.blank?
|
127
|
+
"where " + arg.map do |issue|
|
128
|
+
case issue
|
129
|
+
when String
|
130
|
+
issue
|
131
|
+
when Hash
|
132
|
+
generate_sql_list issue
|
133
|
+
end
|
134
|
+
end.join( ' and ' )
|
135
|
+
end
|
136
|
+
def generate_sql_list attributes={}
|
137
|
+
attributes.map do | key, value |
|
138
|
+
case value
|
139
|
+
when Numeric
|
140
|
+
key.to_s << " = " << value.to_s
|
141
|
+
else # String, Symbol, Date, Time, Trueclass, Falseclass ...
|
142
|
+
key.to_s << ' = ' << "\'#{ value }\'"
|
143
|
+
end
|
144
|
+
end.join( ' and ' )
|
145
|
+
end
|
146
|
+
end # module
|
147
|
+
|
148
|
+
|
149
|
+
class OrientQuery
|
150
|
+
|
151
|
+
include Support
|
152
|
+
|
153
|
+
def initialize **args
|
154
|
+
@projection = []
|
155
|
+
@misc= []
|
156
|
+
args.each do | k,v|
|
157
|
+
self.send k, v
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def method_missing method, *arg, &b
|
162
|
+
@misc << method.to_s << " " << arg.map(&:to_s).join(' ')
|
163
|
+
end
|
164
|
+
|
165
|
+
def misc
|
166
|
+
@misc.join(' ') unless @misc.empty?
|
167
|
+
end
|
168
|
+
|
169
|
+
def subquery
|
170
|
+
nil
|
171
|
+
end
|
172
|
+
|
173
|
+
def compose
|
174
|
+
[ "select", projection, from, where , subquery, misc, order , group_by, unwind, skip ].compact.join(' ')
|
175
|
+
end
|
176
|
+
=begin
|
177
|
+
from can either be a Databaseclass to operate on or a Subquery providing data to query further
|
178
|
+
=end
|
179
|
+
def from arg=nil
|
180
|
+
if arg.present?
|
181
|
+
@database = case arg
|
182
|
+
when Class
|
183
|
+
arg.new.classname
|
184
|
+
when ActiveOrient::Model
|
185
|
+
classname
|
186
|
+
when String
|
187
|
+
arg
|
188
|
+
when Symbol
|
189
|
+
arg
|
190
|
+
when OrientQuery
|
191
|
+
nil # don't set @database
|
192
|
+
end
|
193
|
+
@from = arg
|
194
|
+
else # read from
|
195
|
+
"from " << if @from.is_a?( OrientQuery )
|
196
|
+
"( #{@from.compose} )"
|
197
|
+
else
|
198
|
+
@database.to_s
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
def database_class= arg
|
203
|
+
@database = arg if @database.present?
|
204
|
+
if @from.is_a? OrientQuery
|
205
|
+
@from.database_class= arg
|
206
|
+
end
|
207
|
+
end
|
208
|
+
def database_class
|
209
|
+
if @database.present?
|
210
|
+
@database
|
211
|
+
elsif @from.is_a? OrientQuery
|
212
|
+
@from.database_class
|
213
|
+
else
|
214
|
+
nil
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
=begin
|
220
|
+
Call where without a parameter to request the saved where-string
|
221
|
+
|
222
|
+
to create the where-part of the query a string, a hash or an Array is supported
|
223
|
+
|
224
|
+
where: "r > 9" --> where r > 9
|
225
|
+
where: {a: 9, b: 's'} --> where a = 9 and b = 's'
|
226
|
+
where:[{ a: 2} , 'b > 3',{ c: 'ufz' }] --> where a = 2 and b > 3 and c = 'ufz'
|
227
|
+
=end
|
228
|
+
def where *arg
|
229
|
+
@where= compose_where(*arg) unless arg.empty?
|
230
|
+
@where # return_value
|
231
|
+
end
|
232
|
+
|
233
|
+
def let *arg
|
234
|
+
# SELECT FROM Profile
|
235
|
+
# LET $city = address.city
|
236
|
+
# WHERE $city.name like '%Saint%"' AND
|
237
|
+
# ( $city.country.name = 'Italy' OR $city.country.name = 'France' )
|
238
|
+
puts "OrientSupport::OrientQuery@let is not implementated"
|
239
|
+
end
|
240
|
+
def distinct d=nil
|
241
|
+
if d.present?
|
242
|
+
@projection << case d
|
243
|
+
when String
|
244
|
+
"distinct( #{d} )"
|
245
|
+
when Array
|
246
|
+
"distinct( #{d.first} ) as #{d.last}"
|
247
|
+
when Hash
|
248
|
+
"distinct( #{d.first.first} ) as #{d.first.last}"
|
249
|
+
else
|
250
|
+
""
|
251
|
+
end
|
252
|
+
end
|
253
|
+
@projection.join(' ,') #return_value
|
254
|
+
end
|
255
|
+
def projection s=nil
|
256
|
+
if s.present?
|
257
|
+
|
258
|
+
@projection << case s
|
259
|
+
when Hash
|
260
|
+
s.map{ |x,y| "#{x} as #{y}"}.join( ', ')
|
261
|
+
when Array
|
262
|
+
s.join(', ')
|
263
|
+
else
|
264
|
+
s
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
@projection.join(', ')
|
269
|
+
end
|
270
|
+
|
271
|
+
# def where= w
|
272
|
+
|
273
|
+
# end
|
274
|
+
# select_string = ("select " + select_string + distinct_string + ' from ' + class_name(o_class) ).squeeze(' ')
|
275
|
+
# where_string = compose_where( where )
|
276
|
+
def group_by g=nil
|
277
|
+
@group = "group_by #{g.to_s}" if g.present?
|
278
|
+
# only a string is allowed
|
279
|
+
@group # return_value
|
280
|
+
end
|
281
|
+
def unwind u=nil
|
282
|
+
@unwind = "unwind #{u.to_s}" if u.present?
|
283
|
+
# only a string is allowed
|
284
|
+
@unwind # return_value
|
285
|
+
end
|
286
|
+
|
287
|
+
def skip n=nil
|
288
|
+
@skip= n if n.present?
|
289
|
+
"skip #{n}" if @skip.present?
|
290
|
+
end
|
291
|
+
|
292
|
+
def order o=nil
|
293
|
+
@order_string = "order by " << case o
|
294
|
+
when Hash
|
295
|
+
o.map{ |x,y| "#{x} #{y}" }.join( " " )
|
296
|
+
when Array
|
297
|
+
o.map{ |x| "#{x} asc"}.join( " " )
|
298
|
+
else
|
299
|
+
o.to_s
|
300
|
+
end if o.present?
|
301
|
+
@order_string
|
302
|
+
end
|
303
|
+
# misc_string = if skip > 0 && limit > 0
|
304
|
+
# " skip: #{skip} "
|
305
|
+
# else
|
306
|
+
# ""
|
307
|
+
# end
|
308
|
+
# #
|
309
|
+
#
|
310
|
+
# def compose
|
311
|
+
#
|
312
|
+
# end
|
313
|
+
|
314
|
+
end
|
315
|
+
end # module
|
data/test.rb
ADDED
data/usecase.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
## Usecase
|
2
|
+
Below some typical features are summarized by example
|
3
|
+
|
4
|
+
Start a irb-session and initialize ActiveOrient
|
5
|
+
```ruby
|
6
|
+
topo@gamma:~/new_hctw$ irb
|
7
|
+
2.2.1 :001 > require './config/boot'
|
8
|
+
Using development-environment
|
9
|
+
-------------------- initialize -------------------- => true
|
10
|
+
2.2.1 :002 > ActiveOrient::Model.orientdb = ror = ActiveOrient::OrientDB.new
|
11
|
+
=> #<ActiveOrient::OrientDB:0x000000046f1a90 @res=#<RestClient::Resource:0x000000046c0af8 @url="http://localhost:2480", @block=nil, @options={:user=>"hctw", :password=>"**"}>, @database="hc_database", @classes=[]>
|
12
|
+
```
|
13
|
+
#### Object Mapping
|
14
|
+
Lets create a class, put some content in it and perform basic oo-steps.
|
15
|
+
|
16
|
+
Attributes(Properties) do not have to be formaly declared. However it is nessessary to introduce them properly. This is done with the »attributes«-Argument during the initialisation step or via
|
17
|
+
»update«
|
18
|
+
|
19
|
+
``` ruby
|
20
|
+
A = r.create_class 'my_a_class'
|
21
|
+
=> ActiveOrient::Model::Myaclass
|
22
|
+
a = A.new_document attributes: { test: 45}
|
23
|
+
a.update set: { a_array: aa= [ 1,4,'r', :r ] ,
|
24
|
+
a_hash: { :a => 'b', b: 2 } }
|
25
|
+
a.to_human
|
26
|
+
=> <Myaclass: a_array: [1, 4, "r", :r] a_hash: {:a=>"b", :b=>2} test: 45>
|
27
|
+
|
28
|
+
```
|
29
|
+
Then the attibutes/properties can be handled as normal ruby objects ie.
|
30
|
+
|
31
|
+
``` ruby
|
32
|
+
a.a_array << "a new element"
|
33
|
+
a.a_hash[ :a_new_element ] = "value of the new element"
|
34
|
+
a.test += 3
|
35
|
+
a.test = 567
|
36
|
+
a.update
|
37
|
+
```
|
38
|
+
Objects are synchronized with the database with »update«. To revert changes, a »reload!« method is available.
|
39
|
+
|
40
|
+
#### Contracts-Example
|
41
|
+
Assume a Database, which is defined as
|
42
|
+
```
|
43
|
+
create class Industries
|
44
|
+
create class Categories
|
45
|
+
create class SubCategories
|
46
|
+
create class OpenInterest ABSTRACT
|
47
|
+
create class Stocks extends Contracts
|
48
|
+
create class Futures extends Contracts
|
49
|
+
create class Options extends Contracts
|
50
|
+
create class Forexes extends Contracts
|
51
|
+
create property Industries.categories linkset
|
52
|
+
create property Categories.subcategories linkset
|
53
|
+
create property Categories.industry link
|
54
|
+
create property SubCategories.category link
|
55
|
+
create property SubCategories.contracts linkset
|
56
|
+
|
57
|
+
create property Contracts.subcategory link
|
58
|
+
create property Contracts.details link
|
59
|
+
create property OpenInterest.contracts linkset
|
60
|
+
|
61
|
+
```
|
62
|
+
This defines some conventional relations:
|
63
|
+
|
64
|
+
OpenInterest -> Contracts <- Subcategory <- Category <- Industry
|
65
|
+
|
66
|
+
with some oo-Behavior
|
67
|
+
```ruby
|
68
|
+
2.2.1 :003 > ror.class_hierachie base_class: 'Contracts'
|
69
|
+
=> ["Forexes", "Futures", "Options", "Stocks"]
|
70
|
+
```
|
71
|
+
|
72
|
+
then the following ORM-behavior is implemented:
|
73
|
+
```ruby
|
74
|
+
topo@gamma:~/new_hctw$ irb
|
75
|
+
2.2.1 :001 > require './config/boot'
|
76
|
+
Using development-environment
|
77
|
+
-------------------- initialize -------------------- => true
|
78
|
+
2.2.1 :002 > ActiveOrient::Model.orientdb = ror = ActiveOrient::OrientDB.new
|
79
|
+
=> #<ActiveOrient::OrientDB:0x000000046f1a90 @res=#<RestClient::Resource:0x000000046c0af8 @url="http://localhost:2480", @block=nil, @options={:user=>"hctw", :password=>"**"}>, @database="hc_database", @classes=[]>
|
80
|
+
2.2.1 :003 > OpenInterest = ror.open_class 'Openinterest'
|
81
|
+
=> ActiveOrient::Model::Openinterest
|
82
|
+
2.2.1 :004 > first_open_interest = OpenInterest.first
|
83
|
+
=> #<ActiveOrient::Model::Openinterest:0x0000000443ede8 @metadata={"type"=>"d", "class"=>"Openinterest", "version"=>5, "fieldTypes"=>"fetch_date=t,contracts=z", "cluster"=>13, "record"=>0}, @attributes={"fetch_date"=>"2015-06-02 00:00:00", "contracts"=>["#21:36", "#21:35", "#21:34", "#21:33", "#21:32", "#21:31", "#21:30", "#21:29", "#21:28", "#21:27", "#21:26", "#21:25", "#21:24", "#21:23", "#21:22", "#21:21", "#21:51", "#21:49", "#21:50", "#21:47", "#21:48", "#21:45", "#21:46", "#21:43", "#21:44", "#21:41", "#21:42", "#21:39", "#21:40", "#21:37", "#21:38", "#21:4", "#21:3", "#21:0", "#21:17", "#21:18", "#21:19", "#21:20", "#21:13", "#21:14", "#21:15", "#21:16", "#21:9", "#21:10", "#21:11", "#21:12", "#21:5", "#21:6", "#21:7", "#21:8"], "created_at"=>2015-07-01 15:27:41 +0200, "updated_at"=>2015-07-01 15:27:41 +0200}>
|
84
|
+
2.2.1 :005 > first_open_interest.contracts.first.subcategory.category.industry
|
85
|
+
=> #<ActiveOrient::Model::Industries:0x00000004af88f0 @metadata={"type"=>"d", "class"=>"Industries", "version"=>8, "fieldTypes"=>"categories=n", "cluster"=>17, "record"=>1}, @attributes={"categories"=>["#15:13", "#15:4", "#15:1"], "name"=>"Basic Materials", "created_at"=>2015-07-01 15:27:58 +0200, "updated_at"=>2015-07-01 15:27:58 +0200}>
|
86
|
+
|
87
|
+
2.2.1 :006 > first_open_interest.contracts.first.subcategory.category.industry.name
|
88
|
+
=> "Basic Materials"
|
89
|
+
```
|
90
|
+
|
91
|
+
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active-orient
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- " Hartmut Bischoff"
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Persistent ORM for OrientDB, based on ActiveModel
|
56
|
+
email:
|
57
|
+
- topofocus@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- Gemfile
|
65
|
+
- Guardfile
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- acitve-orient.gemspec
|
69
|
+
- config/boot.rb
|
70
|
+
- config/connect.yml
|
71
|
+
- lib/base.rb
|
72
|
+
- lib/base_properties.rb
|
73
|
+
- lib/model.rb
|
74
|
+
- lib/orient.rb
|
75
|
+
- lib/query.rb
|
76
|
+
- lib/rest.rb
|
77
|
+
- lib/support.rb
|
78
|
+
- test.rb
|
79
|
+
- usecase.md
|
80
|
+
homepage: https://github.com/topofocus/active-orient
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 2.2.0
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.4.6
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Pure ruby client for OrientDB based on ActiveModel
|
104
|
+
test_files: []
|