active-orient 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -2
  3. data/README.md +78 -35
  4. data/VERSION +1 -1
  5. data/active-orient.gemspec +4 -4
  6. data/bin/active-orient-console +8 -5
  7. data/config/boot.rb +2 -4
  8. data/config/config.yml +1 -1
  9. data/config/connect.yml +2 -2
  10. data/examples/time_graph.md +162 -0
  11. data/gratefuldeadconcerts.md +94 -0
  12. data/lib/active-orient.rb +4 -2
  13. data/lib/base.rb +53 -20
  14. data/lib/base_properties.rb +2 -3
  15. data/lib/class_utils.rb +3 -4
  16. data/lib/database_utils.rb +14 -5
  17. data/lib/init.rb +11 -1
  18. data/lib/model/edge.rb +12 -10
  19. data/lib/model/model.rb +17 -3
  20. data/lib/model/the_class.rb +60 -40
  21. data/lib/model/the_record.rb +63 -51
  22. data/lib/model/vertex.rb +114 -10
  23. data/lib/orient.rb +24 -33
  24. data/lib/orientdb_private.rb +31 -31
  25. data/lib/other.rb +55 -5
  26. data/lib/rest/change.rb +17 -4
  27. data/lib/rest/create.rb +38 -24
  28. data/lib/rest/delete.rb +3 -2
  29. data/lib/rest/operations.rb +37 -27
  30. data/lib/rest/read.rb +2 -2
  31. data/lib/rest/rest.rb +4 -3
  32. data/lib/support.rb +17 -16
  33. data/linkmap.md +75 -0
  34. data/namespace.md +111 -0
  35. data/rails.md +125 -0
  36. data/rails/activeorient.rb +53 -0
  37. data/{examples/time_graph/config → rails}/config.yml +3 -1
  38. data/{examples/time_graph/config → rails}/connect.yml +2 -2
  39. data/usecase_oo.md +3 -1
  40. metadata +21 -38
  41. data/examples/createTime.rb +0 -91
  42. data/examples/time_graph/Gemfile +0 -21
  43. data/examples/time_graph/Guardfile +0 -26
  44. data/examples/time_graph/README.md +0 -129
  45. data/examples/time_graph/bin/active-orient-console +0 -35
  46. data/examples/time_graph/config/boot.rb +0 -119
  47. data/examples/time_graph/config/init_db.rb +0 -59
  48. data/examples/time_graph/createTime.rb +0 -51
  49. data/examples/time_graph/lib/createTime.rb +0 -82
  50. data/examples/time_graph/model/day_of.rb +0 -3
  51. data/examples/time_graph/model/e.rb +0 -6
  52. data/examples/time_graph/model/edge.rb +0 -53
  53. data/examples/time_graph/model/monat.rb +0 -19
  54. data/examples/time_graph/model/stunde.rb +0 -16
  55. data/examples/time_graph/model/tag.rb +0 -29
  56. data/examples/time_graph/model/time_base.rb +0 -6
  57. data/examples/time_graph/model/time_of.rb +0 -4
  58. data/examples/time_graph/model/v.rb +0 -3
  59. data/examples/time_graph/model/vertex.rb +0 -32
  60. data/examples/time_graph/spec/lib/create_time_spec.rb +0 -50
  61. data/examples/time_graph/spec/rest_helper.rb +0 -37
  62. data/examples/time_graph/spec/spec_helper.rb +0 -46
  63. data/usecase.md +0 -104
@@ -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
- end
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 = nil, &b
160
- items = block_given? ? yield : nil
161
- update_item_property "ADD", array, item, &b
162
- self # return_value
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
- def set_item_to_property array, item = nil, &b
170
- update_item_property "SET", array, item, &b
172
+
173
+ def set_item_to_property array, *item
174
+ update array.to_s => item
171
175
  end
172
176
 
173
- def remove_item_from_property array, item = nil, &b
174
- update_item_property "REMOVE", array, item, &b
175
- if block_given?
176
- items = yield
177
- items.each{|x| self.attributes[array].delete(x)}
178
- elsif item.present?
179
- a = attributes
180
- a.delete item
181
- self.attributes[array].delete(item)
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 databasea
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['updated_at'] = Time.new
216
- updated_dataset = db.update self, attributes, @metadata[:version]
217
- # if the updated dataset changed, drop the changes made siently
218
- if updated_dataset.is_a? ActiveOrient::Model
219
- self.version = updated_dataset.version
220
- updated_dataset # return_value
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
- logger.error("Version Conflict: reloading database values")
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= DB.create_record self, attributes: attributes
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
 
@@ -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
- # to do
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
- # def delete
10
- # delete an edge (as class method)
11
- # and
12
- # def remove
13
- # delete an edge (as instance method)
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
- end
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
@@ -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
- # print "\n <<---> #{@name}, #{arg} <--- \n"
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
- super
59
- end
60
-
61
- def delete_at *pos
62
- if @name.present?
63
- delete self[*pos]
64
- else
65
- super
66
- end
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
- def delete_if
70
- if @name.present?
71
- delete *self.map{|y| y if yield(y)}.compact # if the block returns true then delete the item
72
- else
73
- super
74
- end
75
- end
66
+ #
67
+ # alias :del_org :delete
68
+ =begin
69
+ Remove performs Array#delete
76
70
 
77
- def delete *item
78
- @orient.remove_item_from_property(@name){item} if @name.present?
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
- begin
97
- map{|x| x.send args.first}
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
 
@@ -13,36 +13,36 @@ module OrientDbPrivate
13
13
  end
14
14
  end
15
15
 
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
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