active-orient 0.4 → 0.5

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +8 -3
  4. data/Guardfile +12 -4
  5. data/README.md +221 -201
  6. data/VERSION +1 -1
  7. data/active-orient.gemspec +3 -2
  8. data/bin/active-orient-console +35 -0
  9. data/config/boot.rb +84 -16
  10. data/config/config.yml +10 -0
  11. data/config/connect.yml +6 -2
  12. data/create_project +19 -0
  13. data/examples/books.rb +86 -39
  14. data/examples/createTime.rb +91 -0
  15. data/examples/streets.rb +85 -84
  16. data/examples/test_commands.rb +92 -0
  17. data/examples/test_commands_2.rb +54 -0
  18. data/examples/test_commands_3.rb +48 -0
  19. data/examples/test_commands_4.rb +28 -0
  20. data/examples/time_graph/Gemfile +21 -0
  21. data/examples/time_graph/Guardfile +26 -0
  22. data/examples/time_graph/README.md +129 -0
  23. data/examples/time_graph/bin/active-orient-console +35 -0
  24. data/examples/time_graph/config/boot.rb +119 -0
  25. data/examples/time_graph/config/config.yml +8 -0
  26. data/examples/time_graph/config/connect.yml +17 -0
  27. data/examples/time_graph/config/init_db.rb +59 -0
  28. data/examples/time_graph/createTime.rb +51 -0
  29. data/examples/time_graph/lib/createTime.rb +82 -0
  30. data/examples/time_graph/model/day_of.rb +3 -0
  31. data/examples/time_graph/model/e.rb +6 -0
  32. data/examples/time_graph/model/edge.rb +53 -0
  33. data/examples/time_graph/model/monat.rb +19 -0
  34. data/examples/time_graph/model/stunde.rb +16 -0
  35. data/examples/time_graph/model/tag.rb +29 -0
  36. data/examples/time_graph/model/time_base.rb +6 -0
  37. data/examples/time_graph/model/time_of.rb +4 -0
  38. data/examples/time_graph/model/v.rb +3 -0
  39. data/examples/time_graph/model/vertex.rb +32 -0
  40. data/examples/time_graph/spec/lib/create_time_spec.rb +50 -0
  41. data/examples/time_graph/spec/rest_helper.rb +37 -0
  42. data/examples/time_graph/spec/spec_helper.rb +46 -0
  43. data/lib/active-orient.rb +56 -6
  44. data/lib/base.rb +149 -147
  45. data/lib/base_properties.rb +40 -41
  46. data/lib/class_utils.rb +301 -0
  47. data/lib/database_utils.rb +97 -0
  48. data/lib/init.rb +35 -0
  49. data/lib/java-api.rb +437 -0
  50. data/lib/jdbc.rb +211 -0
  51. data/lib/model/edge.rb +53 -0
  52. data/lib/model/model.rb +77 -0
  53. data/lib/model/the_class.rb +480 -0
  54. data/lib/model/the_record.rb +310 -0
  55. data/lib/model/vertex.rb +32 -0
  56. data/lib/orient.rb +113 -50
  57. data/lib/orientdb_private.rb +48 -0
  58. data/lib/other.rb +280 -0
  59. data/lib/query.rb +71 -73
  60. data/lib/rest/change.rb +124 -0
  61. data/lib/rest/create.rb +474 -0
  62. data/lib/rest/delete.rb +133 -0
  63. data/lib/rest/operations.rb +150 -0
  64. data/lib/rest/read.rb +150 -0
  65. data/lib/rest/rest.rb +111 -0
  66. data/lib/rest_disabled.rb +24 -0
  67. data/lib/support.rb +387 -296
  68. data/old_lib_functions/two_general_class.rb +139 -0
  69. data/usecase.md +49 -36
  70. data/usecase_oo.md +59 -0
  71. metadata +73 -9
  72. data/lib/model.rb +0 -461
  73. data/lib/rest.rb +0 -1036
  74. data/test.rb +0 -4
@@ -0,0 +1,310 @@
1
+ module ModelRecord
2
+ ############### RECORD FUNCTIONS ###############
3
+
4
+ ############# GET #############
5
+
6
+ def from_orient
7
+ self
8
+ end
9
+
10
+ # Returns just the name of the Class
11
+
12
+ def self.classname # :nodoc:
13
+ self.class.to_s.split(':')[-1]
14
+ end
15
+
16
+ #
17
+ # Obtain the RID of the Record (format: "00:00")
18
+ #
19
+
20
+ def rid
21
+ begin
22
+ "#{@metadata[:cluster]}:#{@metadata[:record]}"
23
+ rescue
24
+ "0:0"
25
+ end
26
+ end
27
+ =begin
28
+ The extended representation of rid (format "#00:00" )
29
+ =end
30
+ def rrid
31
+ "#" + rid
32
+ end
33
+ alias to_orient rrid
34
+
35
+ def to_or
36
+ rrid
37
+ end
38
+ =begin
39
+ Query uses the current model-record as origin of the query
40
+ It sends the OrientSupport::OrientQuery directly to the database and returns a
41
+ ActiveOrient::Model-Object or an Array of Model-Objects as result.
42
+
43
+ =end
44
+
45
+ def query query
46
+
47
+ sql_cmd = -> (command) {{ type: "cmd", language: "sql", command: command }}
48
+ orientdb.execute do
49
+ sql_cmd[query.to_s]
50
+ end
51
+ end
52
+
53
+ =begin
54
+ queries the database starting with the current model-record.
55
+
56
+ Returns the result-set, ie. a Query-Object which contains links to the addressed records.
57
+
58
+ =end
59
+ def find attributes = {}
60
+ q = OrientSupport::OrientQuery.new from: self, where: attributes
61
+ query q
62
+ end
63
+
64
+ # Get the version of the object
65
+ def version # :nodoc:
66
+ if document.present?
67
+ document.version
68
+ else
69
+ @metadata[:version]
70
+ end
71
+ end
72
+
73
+ def version= version # :nodoc:
74
+ @metadata[:version] = version
75
+ end
76
+
77
+ def increment_version # :nodoc:
78
+ @metadata[:version] += 1
79
+ end
80
+ ########### UPDATE PROPERTY ############
81
+
82
+ =begin
83
+ Convient method for populating embedded- or linkset-properties
84
+ In both cases an array/a collection is stored in the database.
85
+ Its called via
86
+ model.add_item_to_property(linkset- or embedded property, Object_to_be_linked_to\)
87
+ or
88
+ mode.add_items_to_property( linkset- or embedded property ) do
89
+ Array_of_Objects_to_be_linked_to
90
+ #(actually, the objects must inherent from ActiveOrient::Model, Numeric, String)
91
+ end
92
+
93
+ The method is aliased by "<<" i.e
94
+ model.array << new_item
95
+ =end
96
+
97
+ def update_item_property method, array, item = nil, &ba # :nodoc:
98
+ # begin
99
+ logger.progname = 'ActiveOrient::Model#UpdateItemToProperty'
100
+ #self.attributes[array] = OrientSupport::Array.new(self) unless attributes[array].present?
101
+ self.attributes[array] = Array.new unless attributes[array].present?
102
+
103
+ items = if item.present?
104
+ item.is_a?(Array)? item : [item]
105
+ elsif block_given?
106
+ yield
107
+ end
108
+ 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
+ end
114
+ =begin
115
+ Add Items to a linked or embedded class
116
+ Parameter
117
+
118
+ array : the name of the property to work on
119
+ item : what to add (optional)
120
+ block: has to provide an array of elements to add to the property
121
+
122
+ example:
123
+
124
+ add_item_to_property :second_list do
125
+ (0 .. 9).map do | s |
126
+ SecondList.create label: s
127
+ end
128
+ end
129
+ adds 10 Elements to the property.
130
+
131
+
132
+ The method returns the model record itself. Thus nested initialisations are possible:
133
+
134
+ ORD.create_classes([:base, :first_list, :second_list ]){ "V" }
135
+ ORD.create_property :base, :first_list, type: :linklist, linkedClass: :first_list
136
+ ORD.create_property :base, :label, index: :unique
137
+ ORD.create_property :first_list, :second_list , type: :linklist, linkedClass: :second_list
138
+ ORD.create_vertex_class :log
139
+ (0 .. 9).each do | b |
140
+ base= Base.create label: b, first_list: []
141
+ base.add_item_to_property :first_list do
142
+ (0 .. 9).map do | f |
143
+ first = FirstList.create label: f, second_list: []
144
+ base.add_item_to_property :first_list , first
145
+ first.add_item_to_property :second_list do
146
+ (0 .. 9).map{| s | SecondList.create label: s }
147
+ end # add item second_list
148
+ end # 0..9 -> f
149
+ end # add item first_list
150
+ end # 0..9 -> b
151
+
152
+
153
+ Record#AddItemToProperty shines with its feature to specify records to insert in a block.
154
+ If only single Items are to insert, use
155
+ model_record.linklist << item
156
+
157
+ =end
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
163
+ 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
+
169
+ def set_item_to_property array, item = nil, &b
170
+ update_item_property "SET", array, item, &b
171
+ end
172
+
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)
182
+ end
183
+ self # return_value
184
+ end
185
+
186
+ ############# DELETE ###########
187
+
188
+ # Removes the Model-Instance from the databasea
189
+ # todo: overloaded in vertex and edge
190
+
191
+ def remove
192
+ orientdb.delete_record self
193
+ ActiveOrient::Base.remove_rid self ##if is_edge? # removes the obj from the rid_store
194
+ end
195
+
196
+ ## delete works for any model-class
197
+ ## it calls delete_record and does not check for dependencies
198
+ alias delete remove
199
+
200
+ ########### UPDATE ############
201
+
202
+ =begin
203
+ Convient update of the dataset by calling sql-patch
204
+
205
+ Previously changed attributes are saved to the database.
206
+ With the optional :set argument ad-hoc attributes can be defined
207
+ obj = ActiveOrient::Model::Contracts.first
208
+ obj.name = 'new_name'
209
+ obj.update set: { yesterdays_event: 35 }
210
+ =end
211
+
212
+ def update set: {}
213
+ logger.progname = 'ActiveOrient::Model#Update'
214
+ 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
+ else
222
+ logger.error("Version Conflict: reloading database values")
223
+ reload!
224
+ end
225
+
226
+ end
227
+ ########## SAVE ############
228
+
229
+ =begin
230
+ Saves the record either
231
+
232
+ * by calling update or
233
+ * by creating the record
234
+
235
+ =end
236
+ def save
237
+ if rid.rid?
238
+ update
239
+ else
240
+ db_object= DB.create_record self, attributes: attributes
241
+ @metadata[:cluster], @metadata[:record] = db_object.rid[0,db_object.rid.size].split(':').map( &:to_i)
242
+ reload! db_object
243
+ end
244
+ end
245
+
246
+ =begin
247
+ Overwrite the attributes with Database-Contents (or attributes provided by the updated_dataset.model-instance)
248
+ =end
249
+
250
+ def reload! updated_dataset = nil
251
+ updated_dataset = db.get_record(rid) if updated_dataset.nil?
252
+ @metadata[:version] = updated_dataset.version
253
+ attributes = updated_dataset.attributes
254
+ self # return_value (otherwise only the attributes would be returned)
255
+ end
256
+
257
+ ########## CHECK PROPERTY ########
258
+
259
+ =begin
260
+ An Edge is defined
261
+ * when inherented from the superclass »E» (formal definition)
262
+ * if it has an in- and an out property
263
+
264
+ Actually we just check the second term as we trust the constuctor to work properly
265
+ =end
266
+
267
+ def is_edge?
268
+ attributes.keys.include?('in') && attributes.keys.include?('out')
269
+ end
270
+
271
+ =begin
272
+ How to handle other calls
273
+
274
+ * if attribute is specified, display it
275
+ * if attribute= is specify, assign to the known property or create a new one
276
+
277
+ =end
278
+ def method_missing *args
279
+ # if the first entry of the parameter-array is a known attribute
280
+ # proceed with the assignment
281
+ if args.size == 1
282
+ attributes.keys.include?( args.first.to_s ) ? attributes[args.first] : nil
283
+ elsif args[0][-1] == "="
284
+ if args.size == 2
285
+ if rid.rid?
286
+ update set:{ args[0][0..-2] => args.last }
287
+ else
288
+ self.attributes[ args[0][0..-2] ] = args.last
289
+ end
290
+ else
291
+ update set: {args[0][0..-2] => args[1 .. -1] } if rid.rid?
292
+ end
293
+ else
294
+ raise NameError
295
+ end
296
+ 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
+ #end
308
+
309
+
310
+ end
@@ -0,0 +1,32 @@
1
+ class V < ActiveOrient::Model
2
+ ## link to the library-class
3
+ # create
4
+ # seems not to be nessesary as its identically to the universal create
5
+
6
+
7
+ # to do
8
+
9
+ # def delete
10
+ # delete an edge (as class method)
11
+ # and
12
+ # def remove
13
+ # delete an edge (as instance method)
14
+
15
+ def edges kind=:all # :all, :in, :out
16
+ expression = case kind
17
+ when :all
18
+ /^in|^out/
19
+ when :in
20
+ /^in/
21
+ when :out
22
+ /^out/
23
+ end
24
+ edges = attributes.keys.find_all{ |x| x =~ expression }
25
+ edges.map{|x| attributes[x]}.flatten
26
+ end
27
+
28
+ def remove
29
+ db.delete_vertex self
30
+ end
31
+
32
+ end
@@ -1,98 +1,161 @@
1
1
  module OrientSupport
2
- =begin
3
- This Module fences specialized ruby objects
4
- =end
2
+
3
+ # This Module fences specialized Ruby objects
5
4
 
6
5
  class Array < Array
7
- include Support
8
- =begin
9
- Initialisation method stores the modelinstance in @orient.
6
+ include OrientSupport::Support
7
+ mattr_accessor :logger
10
8
 
11
- Further a list of array-elements is expected, which are forwarded (as Array) to Array
9
+ =begin
10
+ Initialisation method stores the model-instance to work on in @orient.
11
+ The keyword_parameter "work_on" holds the record to work_ion.
12
+ Ihe second argument is the array to work with
12
13
 
14
+ If instead of a model-instance the model-class is provided, a new model-instance is created and returned
15
+ Its up to the caller to save the new instance in the database
13
16
 
17
+ Further a list of array-elements is expected, which are forwarded (as Array) to Array
14
18
  =end
15
- def initialize modelinstance, *args
16
- @orient = modelinstance
17
- super args
18
- @name = modelinstance.attributes.key(self)
19
-
19
+
20
+ def initialize work_on:, work_with:
21
+ @orient = work_on.class == Class ? work_on.new : work_on
22
+ super work_with
23
+ @name = @orient.attributes.key(self)
24
+ # puts "ORIENT: #{@orient.inspect} "
25
+ @name = yield if @name.nil? && block_given?
26
+ # puts "NAME: #{@name.inspect}"
27
+ # puts "SELF: #{self.inspect}"
20
28
  end
21
29
 
30
+ def record
31
+ @orient
32
+ end
33
+ =begin
34
+ Append the argument to the Array, changes the Array itself.
35
+
36
+ The change is transmitted to the database immediately
37
+ =end
22
38
  def << arg
23
- @orient.add_item_to_property( @name, arg ) if @name.present?
39
+ # print "\n <<---> #{@name}, #{arg} <--- \n"
40
+ if @name.present?
41
+ @orient.add_item_to_property(@name, arg)
42
+ end
24
43
  super
25
44
  end
26
45
 
27
46
  =begin
28
- Updating of single items
47
+ Updating of single items
29
48
 
30
- this only works if the hole embedded Array is previosly loaded into the ruby-array.
49
+ This only works if the hole embedded Array is previously loaded into the Ruby-array.
31
50
  =end
32
-
51
+
33
52
  def []= key, value
34
53
  super
35
- @orient.update set: { @name => self } if @name.present?
54
+ @orient.update set: {@name => self} if @name.present?
36
55
  end
37
56
 
38
57
  def [] *arg
39
- # puts "[] ARG: #{arg.inspect}"
40
- # arg.each{|u| puts "[] #{u.inspect} : #{u.class} " }
41
58
  super
42
-
43
59
  end
44
60
 
45
61
  def delete_at *pos
46
- if @name.present?
47
- delete self[*pos]
62
+ if @name.present?
63
+ delete self[*pos]
48
64
  else
49
- super
65
+ super
50
66
  end
51
- # old version: works only if the hole array is loaded into memory
52
- # self[*pos]=nil
53
- # @orient.update set:{ @name => self.compact }
54
67
  end
55
68
 
56
69
  def delete_if
57
70
  if @name.present?
58
- delete *self.map{|y| y if yield(y) }.compact # if the block returns true then delete the item
71
+ delete *self.map{|y| y if yield(y)}.compact # if the block returns true then delete the item
59
72
  else
60
- super
73
+ super
61
74
  end
62
75
  end
63
76
 
64
77
  def delete *item
65
- @orient.remove_item_from_property( @name ) { item } if @name.present?
78
+ @orient.remove_item_from_property(@name){item} if @name.present?
66
79
  end
67
80
 
81
+ ## just works with Hashes as parameters
68
82
  def where *item
69
- where_string = item.map{|m| where_string = compose_where m }.join( ' and ' )
70
- query = "select from ( select expand( #{@name} ) from #{@orient.classname}) #{where_string} "
71
- puts query
72
- @orient.query query
73
-
83
+ where_string = item.map{|m| where_string = compose_where m}.join(' and ')
84
+ subquery= OrientSupport::OrientQuery.new from: @orient, projection: "expand( #{@name})"
85
+ q= OrientSupport::OrientQuery.new from: subquery, where: item
86
+ # query = "SELECT FROM ( SELECT EXPAND( #{@name} ) FROM #{@orient.classname}) #{where_string} "
87
+ # puts q.compose
88
+ # sql_cmd = -> (command) {{ type: "cmd", language: "sql", command: command }}
89
+ # @orient.orientdb.execute do
90
+ # sql_cmd[query.to_s]
91
+ # end
92
+ @orient.query q
74
93
  end
75
94
 
76
95
  def method_missing *args
77
- map{|x| x.send args.first }
96
+ begin
97
+ map{|x| x.send args.first}
98
+ rescue NoMethodError => e
99
+ logger.progname = "OrientSupport::Array#MethodMissing"
100
+ logger.error{"Undefined method: #{e.message}"}
101
+ end
78
102
  end
79
- end
80
- class LinkMap < OrientSupport::Array
81
103
 
104
+ end #Class
105
+
106
+ class LinkMap < OrientSupport::Array
82
107
  def []= arg
83
108
  end
84
- end
85
-
86
- #
87
- # class Hash < Hash_with_indifferent_access
88
- # # additional and overlayed methods for Hash-Objects in OrientDB
89
- # def initialize modelinstance, *args
90
- # @orient = modelinstance
91
- # super args
92
- # @name = modelinstance.attributes.key(self)
93
- #
109
+ end #Class
110
+
111
+
112
+
113
+
114
+ class Hash < HashWithIndifferentAccess
115
+ include OrientSupport::Support
116
+ def initialize modelinstance, args
117
+ @orient = modelinstance
118
+ super args.from_orient
119
+ # @name is the property of @orient to work on
120
+ @name = modelinstance.attributes.key(self)
121
+ # puts "ORIENT: #{@orient.inspect} "
122
+ @name = yield if @name.nil? && block_given?
123
+ # puts "NAME: #{@name.inspect}"
124
+ # puts "SELF: #{self.inspect}"
125
+ end
126
+
127
+
128
+ def []= key, value
129
+ puts " i will handle this in the future"
130
+ #@orient.attributes[key] = value
131
+
132
+ # r = (@orient.query "update #{@orient.rid} put #{@name} = #{key.to_orient}, #{value.to_orient} RETURN AFTER @this").pop
133
+ super key, value
134
+ @orient.update set:{ @name => self}
135
+ # @orient = @orient.class(@orient.rid){r} if r.is_a? ActiveOrient::Model
136
+ # self[ key ]= value
137
+ # puts self.inspect
138
+ #@orient[@name]=self.merge key => value
139
+ #
140
+ end
141
+
142
+ def delete key
143
+ super key
144
+ @orient.update set:{ @name => self}
145
+ end
146
+
147
+ def delete_if &b
148
+ super &b
149
+ @orient.update set:{ @name => self}
150
+
151
+ end
152
+
153
+ # def <<
154
+
155
+
156
+ # def to_orient
157
+ # self
94
158
  # end
95
- #
96
- # end
97
159
 
98
- end
160
+ end
161
+ end #Module