active-orient 0.42 → 0.79

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 (60) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/Gemfile +13 -5
  4. data/Guardfile +12 -4
  5. data/README.md +67 -280
  6. data/VERSION +1 -1
  7. data/active-orient.gemspec +6 -5
  8. data/bin/active-orient-0.6.gem +0 -0
  9. data/bin/active-orient-console +85 -0
  10. data/config/boot.rb +72 -1
  11. data/config/config.yml +10 -0
  12. data/config/connect.yml +9 -4
  13. data/examples/books.rb +92 -40
  14. data/examples/streets.rb +89 -85
  15. data/examples/test_commands.rb +97 -0
  16. data/examples/test_commands_2.rb +59 -0
  17. data/examples/test_commands_3.rb +55 -0
  18. data/examples/test_commands_4.rb +33 -0
  19. data/examples/time_graph.md +162 -0
  20. data/lib/active-orient.rb +75 -9
  21. data/lib/base.rb +238 -169
  22. data/lib/base_properties.rb +68 -60
  23. data/lib/class_utils.rb +226 -0
  24. data/lib/database_utils.rb +98 -0
  25. data/lib/init.rb +79 -0
  26. data/lib/java-api.rb +442 -0
  27. data/lib/jdbc.rb +211 -0
  28. data/lib/model/custom.rb +26 -0
  29. data/lib/model/edge.rb +70 -0
  30. data/lib/model/model.rb +134 -0
  31. data/lib/model/the_class.rb +607 -0
  32. data/lib/model/the_record.rb +266 -0
  33. data/lib/model/vertex.rb +236 -0
  34. data/lib/orientdb_private.rb +48 -0
  35. data/lib/other.rb +371 -0
  36. data/lib/railtie.rb +68 -0
  37. data/lib/rest/change.rb +147 -0
  38. data/lib/rest/create.rb +279 -0
  39. data/lib/rest/delete.rb +134 -0
  40. data/lib/rest/operations.rb +211 -0
  41. data/lib/rest/read.rb +171 -0
  42. data/lib/rest/rest.rb +112 -0
  43. data/lib/rest_disabled.rb +24 -0
  44. data/lib/support/logging.rb +38 -0
  45. data/lib/support/orient.rb +196 -0
  46. data/lib/support/orientquery.rb +469 -0
  47. data/rails.md +154 -0
  48. data/rails/activeorient.rb +32 -0
  49. data/rails/config.yml +10 -0
  50. data/rails/connect.yml +17 -0
  51. metadata +65 -24
  52. data/active-orient-0.4.gem +0 -0
  53. data/active-orient-0.41.gem +0 -0
  54. data/lib/model.rb +0 -468
  55. data/lib/orient.rb +0 -98
  56. data/lib/query.rb +0 -88
  57. data/lib/rest.rb +0 -1059
  58. data/lib/support.rb +0 -372
  59. data/test.rb +0 -4
  60. data/usecase.md +0 -91
@@ -1,87 +1,96 @@
1
1
  require 'active_model'
2
2
  require 'active_support/concern'
3
- require 'active_support/hash_with_indifferent_access'
3
+ #require 'active_support/hash_with_indifferent_access'
4
4
 
5
5
  module ActiveOrient
6
-
7
- # Module adds prop Macro and
8
6
  module BaseProperties
9
7
  extend ActiveSupport::Concern
10
8
 
11
- ### Instance methods
9
+ # Default presentation of ActiveOrient::Model-Objects
12
10
 
13
- # Default presentation
14
11
  def to_human
15
12
  "<#{self.class.to_s.demodulize}: " + content_attributes.map do |attr, value|
16
- "#{attr}: #{value}" unless value.nil?
17
- end.compact.sort.join(' ') + ">"
13
+ v= case value
14
+ when ActiveOrient::Model
15
+ "< #{self.class.to_.demodulize} : #{value.rrid} >"
16
+ when OrientSupport::Array
17
+ value.rrid #.to_human #.map(&:to_human).join("::")
18
+ else
19
+ value.from_orient
20
+ end
21
+ "%s : %s" % [ attr, v] unless v.nil?
22
+ end.compact.sort.join(', ') + ">".gsub('"' , ' ')
18
23
  end
19
24
 
20
- # Comparison support
21
- def content_attributes
22
- HashWithIndifferentAccess[attributes.reject do |(attr, _)|
23
- attr.to_s =~ /(_count)\z/ ||
24
- [:created_at, :updated_at, :type,
25
- :id, :order_id, :contract_id].include?(attr.to_sym)
25
+ # Comparison support
26
+
27
+ def content_attributes # :nodoc:
28
+ # HashWithIndifferentAccess[attributes.reject do |(attr, _)|
29
+ Hash[attributes.reject do |(attr, _)|
30
+ attr.to_s =~ /(_count)\z/ || attr.to_s =~ /^in_/ || attr.to_s =~ /^out_/ || [:created_at, :updated_at, :type, :id, :order_id, :contract_id].include?(attr.to_sym)
26
31
  end]
27
32
  end
28
33
 
29
- # Update nil attributes from given Hash or model
30
- def update_missing attrs
31
- attrs = attrs.content_attributes unless attrs.kind_of?(Hash)
34
+ # return a string ready to include as embedded document
35
+ def embedded
36
+ { "@type" => 'd', "@class" => self.class.ref_name }
37
+ .merge(content_attributes)
38
+ .map{|y,x| z=''; z << y.to_s << ': ' << x.to_or.to_s }.join(' ,')
39
+
40
+ end
32
41
 
33
- attrs.each { |attr, val| send "#{attr}=", val if send(attr).blank? }
42
+ # Update nil attributes from given Hash or model
43
+
44
+ def update_missing attrs # :nodoc:
45
+ attrs = attrs.content_attributes unless attrs.kind_of?(Hash)
46
+ attrs.each{|attr, val| send "#{attr}=", val if send(attr).blank?}
34
47
  self # for chaining
35
48
  end
36
49
 
37
- # Default Model comparison
38
- def == other
50
+ # Default Model comparison
51
+
52
+ def == other # :nodoc:
39
53
  case other
40
54
  when String # Probably a link or a rid
41
- link == other || rid == other
55
+ "##{rid}" == other || rid == other
42
56
  when ActiveOrient::Model
43
- link == other.link
57
+ rid == other.rid
44
58
  else
45
- content_attributes.keys.inject(true) { |res, key|
46
- res && other.respond_to?(key) && (send(key) == other.send(key)) }
59
+ content_attributes.keys.inject(true){ |res, key|
60
+ res && other.respond_to?(key) && (send(key) == other.send(key))
61
+ }
47
62
  end
48
63
  end
49
64
 
50
- ### Default attributes support
65
+ # Default attributes support
51
66
 
52
67
  def default_attributes
53
- {:created_at => Time.now,
54
- :updated_at => Time.now,
55
- }
68
+ {}
69
+ #{:created_at => DateTime.now }
56
70
  end
57
71
 
58
- def set_attribute_defaults
72
+ def set_attribute_defaults # :nodoc:
59
73
  default_attributes.each do |key, val|
60
74
  self.send("#{key}=", val) if self.send(key).nil?
61
- # self.send("#{key}=", val) if self[key].nil? # Problems with association defaults
62
75
  end
63
76
  end
64
77
 
65
78
  included do
66
-
67
79
  after_initialize :set_attribute_defaults
68
80
 
69
- ### Class macros
81
+ # Class macros
70
82
 
71
- def self.prop *properties
83
+ def self.prop *properties # :nodoc:
72
84
  prop_hash = properties.last.is_a?(Hash) ? properties.pop : {}
73
-
74
85
  properties.each { |names| define_property names, nil }
75
86
  prop_hash.each { |names, type| define_property names, type }
76
87
  end
77
88
 
78
- def self.define_property names, body
89
+ def self.define_property names, body # :nodoc:
79
90
  aliases = [names].flatten
80
91
  name = aliases.shift
81
92
  instance_eval do
82
-
83
93
  define_property_methods name, body
84
-
85
94
  aliases.each do |ali|
86
95
  alias_method "#{ali}", name
87
96
  alias_method "#{ali}=", "#{name}="
@@ -89,8 +98,7 @@ module ActiveOrient
89
98
  end
90
99
  end
91
100
 
92
- def self.define_property_methods name, body={}
93
- #p name, body
101
+ def self.define_property_methods name, body={} # :nodoc:
94
102
  case body
95
103
  when '' # default getter and setter
96
104
  define_property_methods name
@@ -102,25 +110,26 @@ module ActiveOrient
102
110
  :validate => body[2]
103
111
 
104
112
  when Hash # recursion base case
105
- getter = case # Define getter
106
- when body[:get].respond_to?(:call)
107
- body[:get]
108
- when body[:get]
109
- proc { self[name].send "to_#{body[:get]}" }
110
- else
111
- proc { self[name] }
112
- end
113
- define_method name, &getter if getter
114
-
115
- setter = case # Define setter
116
- when body[:set].respond_to?(:call)
117
- body[:set]
118
- when body[:set]
119
- proc { |value| self[name] = value.send "to_#{body[:set]}" }
120
- else
121
- proc { |value| self[name] = value } # p name, value;
122
- end
123
- define_method "#{name}=", &setter if setter
113
+ # puts "NAME: "+name.to_s
114
+ # puts "BODY::"+body.inspect
115
+ getter = case # Define getter
116
+ when body[:get].respond_to?(:call)
117
+ body[:get]
118
+ when body[:get]
119
+ proc{self[name].send "to_#{body[:get]}"}
120
+ else
121
+ proc{self[name]}
122
+ end
123
+ define_method name, &getter if getter
124
+ setter = case # Define setter
125
+ when body[:set].respond_to?(:call)
126
+ body[:set]
127
+ when body[:set]
128
+ proc{|value| self[name] = value.send "to_#{body[:set]}"}
129
+ else
130
+ proc{|value| self[name] = value} # p name, value;
131
+ end
132
+ define_method "#{name}=", &setter if setter
124
133
 
125
134
  # Define validator(s)
126
135
  [body[:validate]].flatten.compact.each do |validator|
@@ -132,16 +141,15 @@ module ActiveOrient
132
141
  end
133
142
  end
134
143
 
135
- # TODO define self[:name] accessors for :virtual and :flag properties
144
+ # todo define self[:name] accessors for :virtual and :flag properties
136
145
 
137
146
  else # setter given
138
147
  define_property_methods name, :set => body, :get => body
139
148
  end
140
149
  end
141
150
 
142
- # Timestamps in lightweight models
143
151
  unless defined?(ActiveRecord::Base) && ancestors.include?(ActiveRecord::Base)
144
- prop :created_at, :updated_at
152
+ prop :created_at #, :updated_at
145
153
  end
146
154
 
147
155
  end # included
@@ -0,0 +1,226 @@
1
+ module ClassUtils
2
+ # ClassUitils is included in Rest- and Java-Api-classes
3
+
4
+ =begin
5
+ Returns a valid database-class name, nil if the class does not exists
6
+ =end
7
+
8
+ def classname name_or_class # :nodoc:
9
+ name = case name_or_class
10
+ when ActiveOrient::Model
11
+ name_or_class.class.ref_name
12
+ when Class
13
+ ActiveOrient.database_classes.key(name_or_class)
14
+ else
15
+ if ActiveOrient.database_classes.has_key?( name_or_class.to_s )
16
+ name_or_class
17
+ else
18
+ logger.progname = 'ClassUtils#Classname'
19
+ logger.warn{ "Classname #{name_or_class.inspect} ://: #{name} not present in #{ActiveOrient.database}" }
20
+ nil
21
+ end
22
+ end
23
+ end
24
+ def allocate_class_in_ruby db_classname, &b
25
+ # retrieve the superclass recursively
26
+
27
+ unless ActiveOrient.database_classes[ db_classname ].is_a? Class
28
+
29
+ s = get_db_superclass( db_classname )
30
+ superclass = if s.present? # get the superclass recusivly
31
+ allocate_class_in_ruby( s, &b )
32
+ else
33
+ ActiveOrient::Model
34
+ end
35
+ # superclass is nil, if allocate_class_in_ruby is recursivley
36
+ # called and the superclass was not established
37
+ if superclass.nil?
38
+ ActiveOrient.database_classes[ db_classname ] = "Superclass model file missing"
39
+ return
40
+ end
41
+ reduced_classname = superclass.namespace_prefix.present? ? db_classname.split( superclass.namespace_prefix ).last : db_classname
42
+ classname = superclass.naming_convention( reduced_classname )
43
+
44
+ the_class = if !( ActiveOrient::Model.namespace.send :const_defined?, classname, false )
45
+ ActiveOrient::Model.namespace.send( :const_set, classname, Class.new( superclass ) )
46
+ elsif ActiveOrient::Model.namespace.send( :const_get, classname).ancestors.include?( ActiveOrient::Model )
47
+ ActiveOrient::Model.namespace.send( :const_get, classname)
48
+ else
49
+ t= ActiveOrient::Model.send :const_set, classname, Class.new( superclass )
50
+ logger.warn{ "Unable to allocate class #{classname} in Namespace #{ActiveOrient::Model.namespace}"}
51
+ logger.warn{ "Allocation took place with namespace ActiveOrient::Model" }
52
+ t
53
+ end
54
+ the_class.ref_name = db_classname
55
+ keep_the_dataset = block_given? ? yield( the_class ) : true
56
+ if keep_the_dataset
57
+ ActiveOrient.database_classes[db_classname] = the_class
58
+ the_class.ref_name = db_classname
59
+ the_class # return the generated class
60
+ else
61
+ unless ["E","V"].include? classname # never remove Base-Classes!
62
+ base_classname = the_class.to_s.split("::").last.to_sym
63
+
64
+ if ActiveOrient::Model.namespace.send( :const_defined? , classname)
65
+ ActiveOrient::Model.namespace.send( :remove_const, classname )
66
+ else
67
+ ActiveOrient::Model.send( :remove_const, classname)
68
+ end
69
+ end
70
+ nil # return-value
71
+ end
72
+ else
73
+ # return previosly allocated ruby-class
74
+ ActiveOrient.database_classes[db_classname]
75
+ end
76
+ end
77
+
78
+ =begin
79
+ create a single class and provide properties as well
80
+
81
+ ORD.create_class( the_class_name as String or Symbol (nessesary) ,
82
+ properties: a Hash with property- and Index-descriptions (optional)) do
83
+ { superclass: The name of the superclass as String or Symbol ,
84
+ abstract: true|false
85
+ }
86
+ end
87
+
88
+ or
89
+
90
+ ORD.create_class( class1, class2 ... ) { Superclass }
91
+
92
+ ORD.create_class( class ) { {superclass: the_superclass_name, abstract: true_or_false } }
93
+
94
+ ORD.create_class class
95
+
96
+ =end
97
+ def create_class( *class_names, properties: nil, &b )
98
+
99
+
100
+ if block_given?
101
+ the_block = yield
102
+ superclass, abstract = if the_block.is_a? Class
103
+ [ the_block, nil ]
104
+ elsif the_block.is_a?(String) || the_block.is_a?(Symbol)
105
+ [ ActiveOrient.database_classes[the_block] , nil ]
106
+ elsif the_block.is_a?(Hash)
107
+ [ ActiveOrient.database_classes[the_block[:superclass]],
108
+ ActiveOrient.database_classes[the_block[:abstract]] ]
109
+ end
110
+ end
111
+ superclass = superclass.presence || ActiveOrient::Model
112
+
113
+
114
+ r= class_names.map do | the_class_name |
115
+ the_class_name = superclass.namespace_prefix + the_class_name.to_s
116
+
117
+ ## lookup the database_classes-Hash
118
+ if ActiveOrient.database_classes[the_class_name].is_a?(Class)
119
+ ActiveOrient.database_classes[the_class_name]
120
+ else
121
+ if superclass =="" || superclass.ref_name == ""
122
+ create_this_class the_class_name
123
+ else
124
+ create_this_class( the_class_name ) do
125
+ if the_block.is_a?(Hash)
126
+ the_block[:superclass] = superclass.ref_name
127
+ the_block
128
+ else
129
+ { superclass: superclass.ref_name }
130
+ end
131
+ end
132
+ end
133
+ database_classes # update_class_array
134
+ create_properties( the_name , properties ) if properties.present?
135
+ allocate_class_in_ruby( the_class_name ) do |that_class|
136
+ keep_the_dataset = true
137
+ end
138
+ end
139
+ end
140
+ r.size==1 ? r.pop : r # return a single class or an array of created classes
141
+ end
142
+
143
+ =begin
144
+ Creates one or more vertex-classes and allocates the provided properties to each class.
145
+
146
+ ORD.create_vertex_class :a
147
+ => A
148
+ ORD.create_vertex_class :a, :b, :c
149
+ => [A, B, C]
150
+ =end
151
+
152
+ def create_vertex_class *name, properties: nil
153
+ r= name.map{|n| create_class( n, properties: properties){ V } }
154
+ r.size == 1 ? r.pop : r
155
+ end
156
+ =begin
157
+ Creates one or more edge-classes and allocates the provided properties to each class.
158
+ =end
159
+
160
+ def create_edge_class *name, properties: nil
161
+ r = name.map{|n| create_class( n.to_s, properties: properties){ E } }
162
+ r.size == 1 ? r.pop : r # returns the created classes as array if multible classes are provided
163
+ end
164
+ =begin
165
+
166
+ creates a vertex
167
+
168
+ =end
169
+ def create_vertex( o_class, attributes:{} )
170
+
171
+ begin
172
+ response = execute(transaction: false, tolerated_error_code: /found duplicated key/) do
173
+ "CREATE VERTEX #{classname(o_class)} CONTENT #{attributes.to_orient.to_json}"
174
+ end
175
+ if response.is_a?(Array) && response.size == 1
176
+ response.pop # RETURN_VALUE
177
+ else
178
+ response # return value (the normal case)
179
+ end
180
+ rescue ArgumentError => e
181
+ puts "CreateVertex:ArgumentError "
182
+ puts e.inspect
183
+ end # begin
184
+
185
+ end
186
+
187
+ =begin
188
+ Deletes the specified vertices and unloads referenced edges from the cache
189
+ =end
190
+ def delete_vertex *vertex
191
+ create_command = -> do
192
+ { type: "cmd",
193
+ language: 'sql',
194
+ command: "DELETE VERTEX #{vertex.map{|x| x.to_orient }.join(',')} "
195
+ }
196
+ end
197
+
198
+ vertex.each{|v| v.edges.each{| e | remove_record_from_hash e} }
199
+ execute{ create_command[] }
200
+ end
201
+
202
+ =begin
203
+ Deletes the specified edges and unloads referenced vertices from the cache
204
+ =end
205
+ def delete_edge *edge
206
+ create_command = -> do
207
+ { type: "cmd",
208
+ language: 'sql',
209
+ command: "DELETE EDGE #{edge.map{|x| x.to_orient }.join(',')} "
210
+ }
211
+ end
212
+
213
+ edge.each do |r|
214
+ [r.in, r.out].each{| e | remove_record_from_hash e}
215
+ remove_record_from_hash r
216
+ end
217
+ execute{ create_command[] }
218
+ end
219
+
220
+ private
221
+ def remove_record_from_hash r
222
+ obj= ActiveOrient::Base.get_rid(r.rid) unless r.nil?
223
+ ActiveOrient::Base.remove_rid( obj ) unless obj.nil?
224
+ end
225
+
226
+ end # module
@@ -0,0 +1,98 @@
1
+ module DatabaseUtils
2
+ =begin
3
+ returns the classes set by OrientDB
4
+
5
+ Parameter:
6
+ abstract: true|false
7
+
8
+ if abstract: true is given, only basic classes (Abstact-Classes) are returend
9
+ =end
10
+ def system_classes abstract: false
11
+
12
+ basic= [ "ORestricted", "OSchedule", "OTriggered", "OSequence"]
13
+ ## "ORid" dropped in V2.2
14
+ extended = ["OIdentity","ORole", "OUser", "OFunction", "_studio"]
15
+ v3 = ["OGeometryCollection", "OLineString", "OMultiLineString", "OMultiPoint", "OMultiPolygon",
16
+ "OPoint", "OPolygon", "ORectangle", "OShape"] ## added in Orentdb 3.0
17
+ if abstract
18
+ basic
19
+ else
20
+ basic + extended + v3
21
+ end
22
+ end
23
+ =begin
24
+ Returns the class_hierachy
25
+
26
+ To fetch all Vertices:
27
+ class_hieararchy(base_class: 'V').flatten
28
+ To fetch all Edges:
29
+ class_hierarchy(base_class: 'E').flatten
30
+ --
31
+ notice:
32
+ To retrieve the class hierarchy from Objects avoid calling `ORD.classname (obj)`, because it depends on class_hierarchy.
33
+ =end
34
+
35
+ def class_hierarchy base_class: '', system_classes: nil
36
+ @actual_class_hash = get_classes('name', 'superClass') #if requery || @all_classes.blank?
37
+ fv = ->( s ) { @actual_class_hash.find_all{|x| x['superClass']== s}.map{|v| v['name']} }
38
+ fx = ->( v ) { fv[v.strip].map{|x| ar = fx[x]; ar.empty? ? x : [x, ar]} }
39
+ if system_classes.present?
40
+ fx[ base_class.to_s ]
41
+ else
42
+ fx[ base_class.to_s ] - system_classes() - [ ["OIdentity", ["ORole", "OUser"]]] - [ ["OShape",["OGeometryCollection","OLineString", "OMultiLineString", "OMultiPoint", "OMultiPolygon", "OPoint", "OPolygon", "ORectangle"] ] ]
43
+ end
44
+ end
45
+
46
+
47
+ =begin
48
+ Returns an array with all names of the classes of the database. Uses a cached version if possible.
49
+
50
+ Parameters: system_classes: false|true, requery: false|true
51
+ =end
52
+
53
+ def database_classes system_classes: nil, requery: false
54
+ class_hierarchy system_classes: system_classes #requery: true
55
+ all_classes = get_classes('name').map(&:values).sort.flatten
56
+ all_user_classes = all_classes - system_classes()
57
+
58
+ all_user_classes.each{|x| ActiveOrient.database_classes[x] = "unset" unless ActiveOrient.database_classes.has_key?(x) }
59
+
60
+ ActiveOrient.database_classes.keys # return an array of database-classnames
61
+ end
62
+
63
+ =begin
64
+ Service-Method for Model#OrientdbClass
65
+ =end
66
+
67
+ def get_db_superclass name #:nodoc:
68
+ @actual_class_hash = get_classes( 'name', 'superClass') if @actual_class_hash.nil?
69
+ z= @actual_class_hash.find{|x,y| x['name'] == name.to_s }
70
+ z['superClass'] unless z.nil?
71
+ end
72
+
73
+ =begin
74
+ preallocate classes reads any class from the @classes-Array and allocates adequat Ruby-Objects
75
+ =end
76
+ def preallocate_classes from_model_dir= nil # :nodoc:
77
+ # always scan for E+V model-file and include
78
+ [E,V].each{|y| y.require_model_file(from_model_dir) }
79
+
80
+ ActiveOrient.database_classes.each do | db_name, the_class |
81
+ allocate_class_in_ruby( db_name ) do |detected_class|
82
+ keep_the_dataset = true
83
+ # keep the class if it is already noted in database_classes
84
+ if ![E,V].include?(detected_class) &&
85
+ !ActiveOrient.database_classes.key( detected_class) &&
86
+ !detected_class.require_model_file(from_model_dir) &&
87
+ !ActiveOrient::Model.keep_models_without_file
88
+
89
+ logger.info{ "#{detected_class.name} --> Class NOT allocated"}
90
+ ActiveOrient.database_classes[ detected_class.ref_name ] = "no model file"
91
+ keep_the_dataset = false
92
+ end
93
+ keep_the_dataset # return_value
94
+ end # block
95
+ end # each iteration
96
+ end # def
97
+
98
+ end # module