active-orient 0.5 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -2
- data/README.md +78 -35
- data/VERSION +1 -1
- data/active-orient.gemspec +4 -4
- data/bin/active-orient-console +8 -5
- data/config/boot.rb +2 -4
- data/config/config.yml +1 -1
- data/config/connect.yml +2 -2
- data/examples/time_graph.md +162 -0
- data/gratefuldeadconcerts.md +94 -0
- data/lib/active-orient.rb +4 -2
- data/lib/base.rb +53 -20
- data/lib/base_properties.rb +2 -3
- data/lib/class_utils.rb +3 -4
- data/lib/database_utils.rb +14 -5
- data/lib/init.rb +11 -1
- data/lib/model/edge.rb +12 -10
- data/lib/model/model.rb +17 -3
- data/lib/model/the_class.rb +60 -40
- data/lib/model/the_record.rb +63 -51
- data/lib/model/vertex.rb +114 -10
- data/lib/orient.rb +24 -33
- data/lib/orientdb_private.rb +31 -31
- data/lib/other.rb +55 -5
- data/lib/rest/change.rb +17 -4
- data/lib/rest/create.rb +38 -24
- data/lib/rest/delete.rb +3 -2
- data/lib/rest/operations.rb +37 -27
- data/lib/rest/read.rb +2 -2
- data/lib/rest/rest.rb +4 -3
- data/lib/support.rb +17 -16
- data/linkmap.md +75 -0
- data/namespace.md +111 -0
- data/rails.md +125 -0
- data/rails/activeorient.rb +53 -0
- data/{examples/time_graph/config → rails}/config.yml +3 -1
- data/{examples/time_graph/config → rails}/connect.yml +2 -2
- data/usecase_oo.md +3 -1
- metadata +21 -38
- data/examples/createTime.rb +0 -91
- data/examples/time_graph/Gemfile +0 -21
- data/examples/time_graph/Guardfile +0 -26
- data/examples/time_graph/README.md +0 -129
- data/examples/time_graph/bin/active-orient-console +0 -35
- data/examples/time_graph/config/boot.rb +0 -119
- data/examples/time_graph/config/init_db.rb +0 -59
- data/examples/time_graph/createTime.rb +0 -51
- data/examples/time_graph/lib/createTime.rb +0 -82
- data/examples/time_graph/model/day_of.rb +0 -3
- data/examples/time_graph/model/e.rb +0 -6
- data/examples/time_graph/model/edge.rb +0 -53
- data/examples/time_graph/model/monat.rb +0 -19
- data/examples/time_graph/model/stunde.rb +0 -16
- data/examples/time_graph/model/tag.rb +0 -29
- data/examples/time_graph/model/time_base.rb +0 -6
- data/examples/time_graph/model/time_of.rb +0 -4
- data/examples/time_graph/model/v.rb +0 -3
- data/examples/time_graph/model/vertex.rb +0 -32
- data/examples/time_graph/spec/lib/create_time_spec.rb +0 -50
- data/examples/time_graph/spec/rest_helper.rb +0 -37
- data/examples/time_graph/spec/spec_helper.rb +0 -46
- data/usecase.md +0 -104
data/lib/model/the_record.rb
CHANGED
@@ -45,10 +45,15 @@ ActiveOrient::Model-Object or an Array of Model-Objects as result.
|
|
45
45
|
def query query
|
46
46
|
|
47
47
|
sql_cmd = -> (command) {{ type: "cmd", language: "sql", command: command }}
|
48
|
-
orientdb.execute do
|
48
|
+
result = orientdb.execute do
|
49
49
|
sql_cmd[query.to_s]
|
50
50
|
end
|
51
|
-
|
51
|
+
if result.is_a? Array
|
52
|
+
OrientSupport::Array.new work_on: self, work_with: result
|
53
|
+
else
|
54
|
+
result
|
55
|
+
end # return value
|
56
|
+
end
|
52
57
|
|
53
58
|
=begin
|
54
59
|
queries the database starting with the current model-record.
|
@@ -97,7 +102,6 @@ Returns the result-set, ie. a Query-Object which contains links to the addressed
|
|
97
102
|
def update_item_property method, array, item = nil, &ba # :nodoc:
|
98
103
|
# begin
|
99
104
|
logger.progname = 'ActiveOrient::Model#UpdateItemToProperty'
|
100
|
-
#self.attributes[array] = OrientSupport::Array.new(self) unless attributes[array].present?
|
101
105
|
self.attributes[array] = Array.new unless attributes[array].present?
|
102
106
|
|
103
107
|
items = if item.present?
|
@@ -106,10 +110,6 @@ Returns the result-set, ie. a Query-Object which contains links to the addressed
|
|
106
110
|
yield
|
107
111
|
end
|
108
112
|
db.manipulate_relation self, method, array, items
|
109
|
-
#rescue RestClient::InternalServerError => e
|
110
|
-
# logger.error{"Duplicate found in #{array}"}
|
111
|
-
# logger.error{e.inspect}
|
112
|
-
# end
|
113
113
|
end
|
114
114
|
=begin
|
115
115
|
Add Items to a linked or embedded class
|
@@ -156,36 +156,42 @@ If only single Items are to insert, use
|
|
156
156
|
|
157
157
|
=end
|
158
158
|
|
159
|
-
def add_item_to_property array, item
|
160
|
-
|
161
|
-
|
162
|
-
|
159
|
+
def add_item_to_property array, *item
|
160
|
+
item = yield if block_given?
|
161
|
+
if attributes.keys.include? array.to_s
|
162
|
+
item.each{|x| self.attributes[array].push x.to_orient }
|
163
|
+
update
|
164
|
+
else
|
165
|
+
update array=> item
|
166
|
+
end
|
167
|
+
# rescue NoMethodError
|
168
|
+
#undefined method `<<' for nil:NilClass
|
169
|
+
|
163
170
|
end
|
164
|
-
# alias add_items_to_property add_item_to_property
|
165
|
-
## historical aliases
|
166
|
-
# alias update_linkset add_item_to_property
|
167
|
-
# alias update_embedded add_item_to_property
|
168
171
|
|
169
|
-
|
170
|
-
|
172
|
+
|
173
|
+
def set_item_to_property array, *item
|
174
|
+
update array.to_s => item
|
171
175
|
end
|
172
176
|
|
173
|
-
def
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
self.attributes[array].delete(
|
177
|
+
def remove_position_from_property array, *pos
|
178
|
+
if attributes[array].is_a? Array
|
179
|
+
pos.each{|x| self.attributes[array].delete_at( x )}
|
180
|
+
update
|
181
|
+
end
|
182
|
+
end
|
183
|
+
def remove_item_from_property array, *item
|
184
|
+
if attributes[array].is_a? Array
|
185
|
+
item.each{|x| self.attributes[array].delete( x.to_orient )}
|
186
|
+
update
|
187
|
+
else
|
188
|
+
logger.error "Wrong attribute: #{attributes[array]}"
|
182
189
|
end
|
183
|
-
self # return_value
|
184
190
|
end
|
185
191
|
|
186
192
|
############# DELETE ###########
|
187
193
|
|
188
|
-
# Removes the Model-Instance from the
|
194
|
+
# Removes the Model-Instance from the database
|
189
195
|
# todo: overloaded in vertex and edge
|
190
196
|
|
191
197
|
def remove
|
@@ -193,8 +199,6 @@ def remove
|
|
193
199
|
ActiveOrient::Base.remove_rid self ##if is_edge? # removes the obj from the rid_store
|
194
200
|
end
|
195
201
|
|
196
|
-
## delete works for any model-class
|
197
|
-
## it calls delete_record and does not check for dependencies
|
198
202
|
alias delete remove
|
199
203
|
|
200
204
|
########### UPDATE ############
|
@@ -207,23 +211,41 @@ alias delete remove
|
|
207
211
|
obj = ActiveOrient::Model::Contracts.first
|
208
212
|
obj.name = 'new_name'
|
209
213
|
obj.update set: { yesterdays_event: 35 }
|
214
|
+
|
215
|
+
** note: The keyword »set« is optional
|
210
216
|
=end
|
211
217
|
|
212
|
-
def update set: {}
|
218
|
+
def update set: {}, **args
|
213
219
|
logger.progname = 'ActiveOrient::Model#Update'
|
214
220
|
self.attributes.merge!(set) if set.present?
|
215
|
-
self.attributes
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
+
self.attributes.merge!(args) if args.present?
|
222
|
+
self.attributes['updated_at'] = DateTime.now
|
223
|
+
if rid.rid?
|
224
|
+
updated_dataset = db.update self, attributes, @metadata[:version]
|
225
|
+
# if the updated dataset changed, drop the changes made siently
|
226
|
+
if updated_dataset.is_a? ActiveOrient::Model
|
227
|
+
self.version = updated_dataset.version
|
228
|
+
updated_dataset # return_value
|
229
|
+
else
|
230
|
+
logger.error("Version Conflict: reloading database values")
|
231
|
+
reload!
|
232
|
+
end
|
221
233
|
else
|
222
|
-
|
223
|
-
reload!
|
234
|
+
save
|
224
235
|
end
|
225
236
|
|
226
237
|
end
|
238
|
+
|
239
|
+
# mocking active record, overrides the base-class-method
|
240
|
+
def update_attribute the_attribute, the_value
|
241
|
+
update set: {the_attribute => the_value }
|
242
|
+
super the_attribute, the_value
|
243
|
+
end
|
244
|
+
|
245
|
+
def update_attributes **args
|
246
|
+
update set: args
|
247
|
+
end
|
248
|
+
|
227
249
|
########## SAVE ############
|
228
250
|
|
229
251
|
=begin
|
@@ -237,7 +259,7 @@ def save
|
|
237
259
|
if rid.rid?
|
238
260
|
update
|
239
261
|
else
|
240
|
-
db_object=
|
262
|
+
db_object= db.create_record self, attributes: attributes
|
241
263
|
@metadata[:cluster], @metadata[:record] = db_object.rid[0,db_object.rid.size].split(':').map( &:to_i)
|
242
264
|
reload! db_object
|
243
265
|
end
|
@@ -250,7 +272,7 @@ end
|
|
250
272
|
def reload! updated_dataset = nil
|
251
273
|
updated_dataset = db.get_record(rid) if updated_dataset.nil?
|
252
274
|
@metadata[:version] = updated_dataset.version
|
253
|
-
attributes = updated_dataset.attributes
|
275
|
+
self.attributes = updated_dataset.attributes
|
254
276
|
self # return_value (otherwise only the attributes would be returned)
|
255
277
|
end
|
256
278
|
|
@@ -294,16 +316,6 @@ How to handle other calls
|
|
294
316
|
raise NameError
|
295
317
|
end
|
296
318
|
end
|
297
|
-
# rescue NameError => e
|
298
|
-
# logger.progname = 'ActiveOrient::Model#MethodMissing'
|
299
|
-
# if args.size == 1
|
300
|
-
# logger.error{"Unknown Attribute: #{args.first} "}
|
301
|
-
# else
|
302
|
-
# logger.error{"Unknown Method: #{args.map{|x| x.to_s}.join(" / ")} "}
|
303
|
-
# end
|
304
|
-
# puts "Method Missing: Args: #{args.inspect}"
|
305
|
-
# print e.backtrace.join("\n")
|
306
|
-
# raise
|
307
319
|
#end
|
308
320
|
|
309
321
|
|
data/lib/model/vertex.rb
CHANGED
@@ -1,16 +1,85 @@
|
|
1
1
|
class V < ActiveOrient::Model
|
2
2
|
## link to the library-class
|
3
|
-
# create
|
4
|
-
# seems not to be nessesary as its identically to the universal create
|
5
|
-
|
6
3
|
|
7
|
-
|
4
|
+
=begin
|
5
|
+
Vertex#delete fires a "delete edge" command to the database.
|
6
|
+
The where statement can be empty ( "" or {}"), then all vertices are removed
|
7
|
+
|
8
|
+
The rid-cache is reseted, too
|
9
|
+
=end
|
10
|
+
def self.delete where:
|
11
|
+
db.execute { "delete vertex #{ref_name} #{db.compose_where(where)}" }
|
12
|
+
reset_rid_store
|
13
|
+
end
|
14
|
+
|
15
|
+
def detect_inherent_edge kind, edge_name # :nodoc:
|
16
|
+
## returns a list of inherented classes
|
17
|
+
get_superclass = ->(e) do
|
18
|
+
n = ORD.get_db_superclass(e)
|
19
|
+
n =='E' ? e : e + ',' + get_superclass[n]
|
20
|
+
end
|
21
|
+
if edge_name.present?
|
22
|
+
e_name = edge_name.is_a?( Class) ? edge_name.ref_name : edge_name.to_s
|
23
|
+
the_edge = @metadata[:edges][kind].detect{|y| get_superclass[y].split(',').detect{|x| x == edge_name } }
|
24
|
+
|
25
|
+
candidate= attributes["#{kind.to_s}_#{the_edge}"]
|
26
|
+
candidate.present? ? candidate.map( &:from_orient ) : []
|
27
|
+
else
|
28
|
+
edges(kind).map &:from_orient
|
29
|
+
end
|
30
|
+
end
|
31
|
+
=begin
|
32
|
+
»in« and »out« provide the main access to edges.
|
33
|
+
|
34
|
+
If called without a parameter, all edges connected are displayed.
|
35
|
+
|
36
|
+
If called with a string, symbol or class, the edge-class is resolved and even inherented
|
37
|
+
edges are retrieved.
|
38
|
+
|
39
|
+
=end
|
40
|
+
|
41
|
+
def in edge_name= nil
|
42
|
+
detect_inherent_edge :in, edge_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def out edge_name = nil
|
46
|
+
detect_inherent_edge :out, edge_name
|
47
|
+
end
|
48
|
+
=begin
|
49
|
+
retrieves connected edges
|
50
|
+
|
51
|
+
The basic ussage is to fetch all/ incomming/ outgoing edges
|
52
|
+
|
53
|
+
Model-Instance.edges :in # :out | :all
|
54
|
+
|
55
|
+
One can filter specific edges by providing parts of the edge-name
|
56
|
+
|
57
|
+
Model-Instance.edges 'in_sector'
|
58
|
+
Model-Instance.edges /sector/
|
59
|
+
|
60
|
+
returns an array of rid's
|
8
61
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
|
62
|
+
example:
|
63
|
+
|
64
|
+
Industry.first.attributes.keys
|
65
|
+
=> ["in_sector_classification", "k", "name", "created_at", "updated_at"] # edge--> in ...
|
66
|
+
|
67
|
+
Industry.first.edges :out
|
68
|
+
=> []
|
69
|
+
|
70
|
+
Industry.first.edges :in
|
71
|
+
=> ["#61:0", "#61:9", "#61:21", "#61:33", "#61:39", "#61:93", "#61:120", "#61:150", "#61:240", "#61:252", "#61:264", "#61:279", "#61:303", "#61:339" ...]
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
To fetch the associated records use the ActiveOrient::Model.autoload_object method
|
76
|
+
|
77
|
+
ActiveOrient::Model.autoload_object Industry.first.edges( :in).first
|
78
|
+
# or
|
79
|
+
Industry.autoload_object Industry.first.edges( /sector/ ).first
|
80
|
+
=> #<SectorClassification:0x00000002daad20 @metadata={"type"=>"d", "class"=>"sector_classification", "version"=>1, "fieldTypes"=>"out=x,in=x", "cluster"=>61, "record"=>0},(...)
|
81
|
+
|
82
|
+
=end
|
14
83
|
|
15
84
|
def edges kind=:all # :all, :in, :out
|
16
85
|
expression = case kind
|
@@ -20,11 +89,46 @@ class V < ActiveOrient::Model
|
|
20
89
|
/^in/
|
21
90
|
when :out
|
22
91
|
/^out/
|
23
|
-
|
92
|
+
when String
|
93
|
+
/#{kind}/
|
94
|
+
when Regexp
|
95
|
+
kind
|
96
|
+
else
|
97
|
+
return []
|
98
|
+
end
|
99
|
+
|
24
100
|
edges = attributes.keys.find_all{ |x| x =~ expression }
|
25
101
|
edges.map{|x| attributes[x]}.flatten
|
26
102
|
end
|
27
103
|
|
104
|
+
=begin
|
105
|
+
»in_edges« and »out_edges« are shortcuts to »edges :in« and »edges :out«
|
106
|
+
|
107
|
+
Its easy to expand the result:
|
108
|
+
tg.out( :ohlc).out.out_edges
|
109
|
+
=> [["#102:11032", "#121:0"]]
|
110
|
+
tg.out( :ohlc).out.out_edges.from_orient
|
111
|
+
=> [[#<TG::GRID_OF:0x00000002620e38
|
112
|
+
|
113
|
+
this displays the out-edges correctly
|
114
|
+
|
115
|
+
whereas
|
116
|
+
tg.out( :ohlc).out.edges( :out)
|
117
|
+
=> [["#101:11032", "#102:11032", "#94:10653", "#121:0"]]
|
118
|
+
|
119
|
+
returns all edges. The parameter (:out) is not recognized, because out is already a nested array.
|
120
|
+
|
121
|
+
this
|
122
|
+
tg.out( :ohlc).first.out.edges( :out)
|
123
|
+
is a walkaround, but using in_- and out_edges is more elegant.
|
124
|
+
=end
|
125
|
+
def in_edges
|
126
|
+
edges :in
|
127
|
+
end
|
128
|
+
def out_edges
|
129
|
+
edges :out
|
130
|
+
end
|
131
|
+
|
28
132
|
def remove
|
29
133
|
db.delete_vertex self
|
30
134
|
end
|
data/lib/orient.rb
CHANGED
@@ -35,11 +35,8 @@ Append the argument to the Array, changes the Array itself.
|
|
35
35
|
|
36
36
|
The change is transmitted to the database immediately
|
37
37
|
=end
|
38
|
-
def << arg
|
39
|
-
|
40
|
-
if @name.present?
|
41
|
-
@orient.add_item_to_property(@name, arg)
|
42
|
-
end
|
38
|
+
def << *arg
|
39
|
+
@orient.add_item_to_property(@name, *arg) if @name.present?
|
43
40
|
super
|
44
41
|
end
|
45
42
|
|
@@ -54,33 +51,32 @@ The change is transmitted to the database immediately
|
|
54
51
|
@orient.update set: {@name => self} if @name.present?
|
55
52
|
end
|
56
53
|
|
57
|
-
def [] *arg
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
54
|
+
# def [] *arg
|
55
|
+
# #puts "ARG #{arg}"
|
56
|
+
# super
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
=begin
|
60
|
+
Remove_at performs Array#delete_at
|
61
|
+
=end
|
62
|
+
def remove_at *pos
|
63
|
+
@orient.remove_position_from_property(@name,*pos) if @name.present?
|
67
64
|
end
|
68
65
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
super
|
74
|
-
end
|
75
|
-
end
|
66
|
+
#
|
67
|
+
# alias :del_org :delete
|
68
|
+
=begin
|
69
|
+
Remove performs Array#delete
|
76
70
|
|
77
|
-
|
78
|
-
|
71
|
+
If the Array-element is a link, this is removed, the linked table is untouched
|
72
|
+
=end
|
73
|
+
def remove *item
|
74
|
+
@orient.remove_item_from_property(@name,*item) if @name.present?
|
79
75
|
end
|
80
|
-
|
76
|
+
###
|
81
77
|
## just works with Hashes as parameters
|
82
78
|
def where *item
|
83
|
-
where_string = item.map{|m| where_string = compose_where m}.join(' and ')
|
79
|
+
where_string = item.map{|m| where_string = compose_where( m ) }.join(' and ')
|
84
80
|
subquery= OrientSupport::OrientQuery.new from: @orient, projection: "expand( #{@name})"
|
85
81
|
q= OrientSupport::OrientQuery.new from: subquery, where: item
|
86
82
|
# query = "SELECT FROM ( SELECT EXPAND( #{@name} ) FROM #{@orient.classname}) #{where_string} "
|
@@ -93,12 +89,11 @@ The change is transmitted to the database immediately
|
|
93
89
|
end
|
94
90
|
|
95
91
|
def method_missing *args
|
96
|
-
|
97
|
-
map{|x| x.send args
|
92
|
+
|
93
|
+
map{|x| x.send *args }
|
98
94
|
rescue NoMethodError => e
|
99
95
|
logger.progname = "OrientSupport::Array#MethodMissing"
|
100
96
|
logger.error{"Undefined method: #{e.message}"}
|
101
|
-
end
|
102
97
|
end
|
103
98
|
|
104
99
|
end #Class
|
@@ -150,10 +145,6 @@ The change is transmitted to the database immediately
|
|
150
145
|
|
151
146
|
end
|
152
147
|
|
153
|
-
# def <<
|
154
|
-
|
155
|
-
|
156
|
-
# def to_orient
|
157
148
|
# self
|
158
149
|
# end
|
159
150
|
|
data/lib/orientdb_private.rb
CHANGED
@@ -13,36 +13,36 @@ module OrientDbPrivate
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
16
|
+
def property_uri this_classname
|
17
|
+
if block_given?
|
18
|
+
"property/#{@database}/#{this_classname}/" << yield
|
19
|
+
else
|
20
|
+
"property/#{@database}/#{this_classname}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.simple_uri *names
|
25
|
+
names.each do |name|
|
26
|
+
m_name = ("#{name.to_s}_uri").to_sym
|
27
|
+
define_method(m_name) do |&b|
|
28
|
+
if b
|
29
|
+
"#{name.to_s}/#{@database}/#{b.call}"
|
30
|
+
else
|
31
|
+
"#{name.to_s}/#{@database}"
|
32
|
+
end # branch
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.sql_uri *names
|
38
|
+
names.each do |name|
|
39
|
+
define_method(("#{name.to_s}_sql_uri").to_sym) do
|
40
|
+
"#{name.to_s}/#{@database}/sql/"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
simple_uri :database, :document, :class, :batch, :function
|
46
|
+
sql_uri :command, :query
|
47
47
|
|
48
48
|
end
|