active-orient 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
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