active-orient 0.42 → 0.79

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