active-orient 0.5 → 0.6
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 +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
|