active-orient 0.4 → 0.80

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 (61) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.graphs.txt.swp +0 -0
  4. data/Gemfile +9 -5
  5. data/Guardfile +12 -4
  6. data/README.md +70 -281
  7. data/VERSION +1 -1
  8. data/active-orient.gemspec +9 -7
  9. data/bin/active-orient-0.6.gem +0 -0
  10. data/bin/active-orient-console +97 -0
  11. data/changelog.md +60 -0
  12. data/config/boot.rb +70 -17
  13. data/config/config.yml +10 -0
  14. data/config/connect.yml +11 -6
  15. data/examples/books.rb +154 -65
  16. data/examples/streets.rb +89 -85
  17. data/graphs.txt +70 -0
  18. data/lib/active-orient.rb +78 -6
  19. data/lib/base.rb +266 -168
  20. data/lib/base_properties.rb +76 -65
  21. data/lib/class_utils.rb +187 -0
  22. data/lib/database_utils.rb +99 -0
  23. data/lib/init.rb +80 -0
  24. data/lib/java-api.rb +442 -0
  25. data/lib/jdbc.rb +211 -0
  26. data/lib/model/custom.rb +29 -0
  27. data/lib/model/e.rb +6 -0
  28. data/lib/model/edge.rb +114 -0
  29. data/lib/model/model.rb +134 -0
  30. data/lib/model/the_class.rb +657 -0
  31. data/lib/model/the_record.rb +313 -0
  32. data/lib/model/vertex.rb +371 -0
  33. data/lib/orientdb_private.rb +48 -0
  34. data/lib/other.rb +423 -0
  35. data/lib/railtie.rb +68 -0
  36. data/lib/rest/change.rb +150 -0
  37. data/lib/rest/create.rb +287 -0
  38. data/lib/rest/delete.rb +150 -0
  39. data/lib/rest/operations.rb +222 -0
  40. data/lib/rest/read.rb +189 -0
  41. data/lib/rest/rest.rb +120 -0
  42. data/lib/rest_disabled.rb +24 -0
  43. data/lib/support/conversions.rb +42 -0
  44. data/lib/support/default_formatter.rb +7 -0
  45. data/lib/support/errors.rb +41 -0
  46. data/lib/support/logging.rb +38 -0
  47. data/lib/support/orient.rb +305 -0
  48. data/lib/support/orientquery.rb +647 -0
  49. data/lib/support/query.rb +92 -0
  50. data/rails.md +154 -0
  51. data/rails/activeorient.rb +32 -0
  52. data/rails/config.yml +10 -0
  53. data/rails/connect.yml +17 -0
  54. metadata +89 -30
  55. data/lib/model.rb +0 -461
  56. data/lib/orient.rb +0 -98
  57. data/lib/query.rb +0 -88
  58. data/lib/rest.rb +0 -1036
  59. data/lib/support.rb +0 -347
  60. data/test.rb +0 -4
  61. data/usecase.md +0 -91
@@ -1,85 +1,97 @@
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
12
-
13
- # Default presentation
14
- def to_human
15
- "<#{self.class.to_s.demodulize}: " + content_attributes.map do |attr, value|
16
- "#{attr}: #{value}" unless value.nil?
17
- end.compact.sort.join(' ') + ">"
18
- end
19
-
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)
9
+ # Default presentation of ActiveOrient::Model-Objects
10
+
11
+ def to_human
12
+ "<#{self.class.to_s.demodulize}: " + content_attributes.map do |attr, value|
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('"' , ' ')
23
+ end
24
+
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
-
29
- # Update nil attributes from given Hash or model
30
- def update_missing attrs
33
+ # return a string ready to include as embedded document
34
+ # used by Model.to_or
35
+ #
36
+ def embedded
37
+ { "@type" => 'd', "@class" => self.class.ref_name }
38
+ .merge(content_attributes)
39
+ .map{|y,x| z=''; z << y.to_s << ': ' << x.to_or.to_s }.join(' ,')
40
+
41
+ end
42
+
43
+ # Update nil attributes from given Hash or model
44
+
45
+ def update_missing attrs # :nodoc:
31
46
  attrs = attrs.content_attributes unless attrs.kind_of?(Hash)
32
-
33
- attrs.each { |attr, val| send "#{attr}=", val if send(attr).blank? }
47
+ attrs.each{|attr, val| send "#{attr}=", val if send(attr).blank?}
34
48
  self # for chaining
35
49
  end
36
50
 
37
- # Default Model comparison
38
- def == other
51
+ # Default Model comparison
52
+
53
+ def == other # :nodoc:
39
54
  case other
40
55
  when String # Probably a link or a rid
41
- link == other || rid == other
56
+ "##{rid}" == other || rid == other
57
+ when ActiveOrient::Model
58
+ rid == other.rid
42
59
  else
43
- content_attributes.keys.inject(true) { |res, key|
44
- res && other.respond_to?(key) && (send(key) == other.send(key)) }
60
+ content_attributes.keys.inject(true){ |res, key|
61
+ res && other.respond_to?(key) && (send(key) == other.send(key))
62
+ }
45
63
  end
46
64
  end
47
65
 
48
- ### Default attributes support
66
+ # Default attributes support
49
67
 
50
68
  def default_attributes
51
- {:created_at => Time.now,
52
- :updated_at => Time.now,
53
- }
69
+ {}
70
+ #{:created_at => DateTime.now }
54
71
  end
55
72
 
56
- def set_attribute_defaults
73
+ def set_attribute_defaults # :nodoc:
57
74
  default_attributes.each do |key, val|
58
75
  self.send("#{key}=", val) if self.send(key).nil?
59
- # self.send("#{key}=", val) if self[key].nil? # Problems with association defaults
60
76
  end
61
77
  end
62
78
 
63
79
  included do
64
-
65
80
  after_initialize :set_attribute_defaults
66
81
 
67
- ### Class macros
82
+ # Class macros
68
83
 
69
- def self.prop *properties
84
+ def self.prop *properties # :nodoc:
70
85
  prop_hash = properties.last.is_a?(Hash) ? properties.pop : {}
71
-
72
86
  properties.each { |names| define_property names, nil }
73
87
  prop_hash.each { |names, type| define_property names, type }
74
88
  end
75
89
 
76
- def self.define_property names, body
90
+ def self.define_property names, body # :nodoc:
77
91
  aliases = [names].flatten
78
92
  name = aliases.shift
79
93
  instance_eval do
80
-
81
94
  define_property_methods name, body
82
-
83
95
  aliases.each do |ali|
84
96
  alias_method "#{ali}", name
85
97
  alias_method "#{ali}=", "#{name}="
@@ -87,8 +99,7 @@ module ActiveOrient
87
99
  end
88
100
  end
89
101
 
90
- def self.define_property_methods name, body={}
91
- #p name, body
102
+ def self.define_property_methods name, body={} # :nodoc:
92
103
  case body
93
104
  when '' # default getter and setter
94
105
  define_property_methods name
@@ -100,25 +111,26 @@ module ActiveOrient
100
111
  :validate => body[2]
101
112
 
102
113
  when Hash # recursion base case
103
- getter = case # Define getter
104
- when body[:get].respond_to?(:call)
105
- body[:get]
106
- when body[:get]
107
- proc { self[name].send "to_#{body[:get]}" }
108
- else
109
- proc { self[name] }
110
- end
111
- define_method name, &getter if getter
112
-
113
- setter = case # Define setter
114
- when body[:set].respond_to?(:call)
115
- body[:set]
116
- when body[:set]
117
- proc { |value| self[name] = value.send "to_#{body[:set]}" }
118
- else
119
- proc { |value| self[name] = value } # p name, value;
120
- end
121
- define_method "#{name}=", &setter if setter
114
+ # puts "NAME: "+name.to_s
115
+ # puts "BODY::"+body.inspect
116
+ getter = case # Define getter
117
+ when body[:get].respond_to?(:call)
118
+ body[:get]
119
+ when body[:get]
120
+ proc{self[name].send "to_#{body[:get]}"}
121
+ else
122
+ proc{self[name]}
123
+ end
124
+ define_method name, &getter if getter
125
+ setter = case # Define setter
126
+ when body[:set].respond_to?(:call)
127
+ body[:set]
128
+ when body[:set]
129
+ proc{|value| self[name] = value.send "to_#{body[:set]}"}
130
+ else
131
+ proc{|value| self[name] = value} # p name, value;
132
+ end
133
+ define_method "#{name}=", &setter if setter
122
134
 
123
135
  # Define validator(s)
124
136
  [body[:validate]].flatten.compact.each do |validator|
@@ -130,16 +142,15 @@ module ActiveOrient
130
142
  end
131
143
  end
132
144
 
133
- # TODO define self[:name] accessors for :virtual and :flag properties
145
+ # todo define self[:name] accessors for :virtual and :flag properties
134
146
 
135
147
  else # setter given
136
148
  define_property_methods name, :set => body, :get => body
137
149
  end
138
150
  end
139
151
 
140
- # Timestamps in lightweight models
141
152
  unless defined?(ActiveRecord::Base) && ancestors.include?(ActiveRecord::Base)
142
- prop :created_at, :updated_at
153
+ prop :created_at #, :updated_at
143
154
  end
144
155
 
145
156
  end # included
@@ -0,0 +1,187 @@
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
+
7
+ works on the cached hash (ActiveOrient.database_classes)
8
+ =end
9
+
10
+ def classname name_or_class # :nodoc:
11
+ name = case name_or_class
12
+ when ActiveOrient::Model
13
+ name_or_class.class.ref_name
14
+ when Class
15
+ ActiveOrient.database_classes.key(name_or_class)
16
+ else
17
+ if ActiveOrient.database_classes.has_key?( name_or_class.to_s )
18
+ name_or_class
19
+ else
20
+ logger.progname = 'ClassUtils#Classname'
21
+ logger.warn{ "Classname #{name_or_class.inspect} ://: #{name} not present in #{ActiveOrient.database}" }
22
+ nil
23
+ end
24
+ end
25
+ end
26
+
27
+ # Updates ActiveOrient.database_classes
28
+ def allocate_class_in_ruby db_classname, &b
29
+
30
+ # first retrieve the superclass recursively
31
+ unless ActiveOrient.database_classes[ db_classname ].is_a? Class
32
+
33
+ s = get_db_superclass( db_classname )
34
+ superclass = if s.present? # get the superclass recusivly
35
+ allocate_class_in_ruby( s, &b )
36
+ else
37
+ ActiveOrient::Model
38
+ end
39
+ # superclass is nil, if allocate_class_in_ruby is recursivley
40
+ # called and the superclass was not established
41
+ if superclass.nil?
42
+ ActiveOrient.database_classes[ db_classname ] = "Superclass model file missing"
43
+ return
44
+ end
45
+ reduced_classname = superclass.namespace_prefix.present? ? db_classname.split( superclass.namespace_prefix ).last : db_classname
46
+ classname = superclass.naming_convention( reduced_classname )
47
+
48
+ the_class = if !( ActiveOrient::Model.namespace.send :const_defined?, classname, false )
49
+ ActiveOrient::Model.namespace.send( :const_set, classname, Class.new( superclass ) )
50
+ elsif ActiveOrient::Model.namespace.send( :const_get, classname).ancestors.include?( ActiveOrient::Model )
51
+ ActiveOrient::Model.namespace.send( :const_get, classname)
52
+ else
53
+ logger.error{ "Unable to allocate class #{classname} in Namespace #{ActiveOrient::Model.namespace}"}
54
+ logger.error{ "Allocation took place with namespace ActiveOrient::Model" }
55
+ ActiveOrient::Model.send :const_set, classname, Class.new( superclass )
56
+ end
57
+ the_class.ref_name = db_classname
58
+ keep_the_dataset = block_given? ? yield( the_class ) : true
59
+ if keep_the_dataset
60
+ ActiveOrient.database_classes[db_classname] = the_class
61
+ the_class.ref_name = db_classname
62
+ the_class # return the generated class
63
+ else
64
+ unless ["E","V"].include? classname # never remove Base-Classes!
65
+ base_classname = the_class.to_s.split("::").last.to_sym
66
+
67
+ if ActiveOrient::Model.namespace.send( :const_defined? , classname)
68
+ ActiveOrient::Model.namespace.send( :remove_const, classname )
69
+ else
70
+ ActiveOrient::Model.send( :remove_const, classname)
71
+ end
72
+ end
73
+ nil # return-value
74
+ end
75
+ else
76
+ # return previously allocated ruby-class
77
+ ActiveOrient.database_classes[db_classname]
78
+ end
79
+ end
80
+
81
+ =begin
82
+ create a single class and provide properties as well
83
+
84
+ ORD.create_class( the_class_name as String or Symbol (nessesary) ,
85
+ properties: a Hash with property- and Index-descriptions (optional)) do
86
+ { superclass: The name of the superclass as String or Symbol ,
87
+ abstract: true|false
88
+ }
89
+ end
90
+
91
+ or
92
+
93
+ ORD.create_class( class1, class2 ... ) { Superclass }
94
+
95
+ ORD.create_class( class ) { {superclass: the_superclass_name, abstract: true_or_false } }
96
+
97
+ ORD.create_class class
98
+
99
+ =end
100
+ def create_class( *class_names, properties: nil, &b )
101
+
102
+
103
+ if block_given?
104
+ the_block = yield
105
+ superclass, abstract = if the_block.is_a? Class
106
+ [ the_block, nil ]
107
+ elsif the_block.is_a?(String) || the_block.is_a?(Symbol)
108
+ [ ActiveOrient.database_classes[the_block] , nil ]
109
+ elsif the_block.is_a?(Hash)
110
+ [ ActiveOrient.database_classes[the_block[:superclass]],
111
+ ActiveOrient.database_classes[the_block[:abstract]] ]
112
+ end
113
+ end
114
+ superclass = superclass.presence || ActiveOrient::Model
115
+
116
+
117
+ r= class_names.map do | the_class_name |
118
+ the_class_name = superclass.namespace_prefix + the_class_name.to_s
119
+
120
+ ## lookup the database_classes-Hash
121
+ if ActiveOrient.database_classes[the_class_name].is_a?(Class)
122
+ ActiveOrient.database_classes[the_class_name]
123
+ else
124
+ if superclass =="" || superclass.ref_name == ""
125
+ create_this_class the_class_name
126
+ else
127
+ create_this_class( the_class_name ) do
128
+ if the_block.is_a?(Hash)
129
+ the_block[:superclass] = superclass.ref_name
130
+ the_block
131
+ else
132
+ { superclass: superclass.ref_name }
133
+ end
134
+ end
135
+ end
136
+ database_classes # update_class_array
137
+ create_properties( the_name , properties ) if properties.present?
138
+ allocate_class_in_ruby( the_class_name ) do |that_class|
139
+ keep_the_dataset = true
140
+ end
141
+ end
142
+ end
143
+ r.size==1 ? r.pop : r # return a single class or an array of created classes
144
+ end
145
+
146
+ =begin
147
+ Creates one or more vertex-classes and allocates the provided properties to each class.
148
+
149
+ ORD.create_vertex_class :a
150
+ => A
151
+ ORD.create_vertex_class :a, :b, :c
152
+ => [A, B, C]
153
+ =end
154
+
155
+ def create_vertex_class *name, properties: nil
156
+ r= name.map{|n| create_class( n, properties: properties){ V } }
157
+ r.size == 1 ? r.pop : r
158
+ end
159
+ =begin
160
+ Creates one or more edge-classes and allocates the provided properties to each class.
161
+ =end
162
+
163
+ def create_edge_class *name, properties: nil
164
+ r = name.map{|n| create_class( n.to_s, properties: properties){ E } }
165
+ r.size == 1 ? r.pop : r # returns the created classes as array if multible classes are provided
166
+ end
167
+
168
+
169
+ =begin
170
+ Deletes the specified edges and unloads referenced vertices from the cache
171
+ =end
172
+ def delete_edge *edge
173
+
174
+ edge.each do |r|
175
+ [r.in, r.out].each{| e | remove_record_from_hash e}
176
+ remove_record_from_hash r
177
+ end
178
+ execute{ "DELETE EDGE #{edge.map{|x| x.to_orient }.join(',')} "}
179
+ end
180
+
181
+ private
182
+ def remove_record_from_hash r
183
+ obj= ActiveOrient::Base.get_rid(r.rid) unless r.nil?
184
+ ActiveOrient::Base.remove_rid( obj ) unless obj.nil?
185
+ end
186
+
187
+ end # module
@@ -0,0 +1,99 @@
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", 'OSecurityPolicy'] ## added in Orentdb 3.0 and 3.1
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
+
49
+ Returns an array with all names of the classes of the database.
50
+
51
+ Reads the database-structure and updates the @actual_class_hash (used by class_hierachy and get_db_superclass )
52
+
53
+ =end
54
+
55
+ def database_classes system_classes: nil
56
+ @actual_class_hash = get_classes('name', 'superClass')
57
+ all_classes = get_classes('name').map(&:values).sort.flatten
58
+ all_user_classes = all_classes - system_classes()
59
+
60
+ all_user_classes.each{|x| ActiveOrient.database_classes[x] = "unset" unless ActiveOrient.database_classes.has_key?(x) }
61
+
62
+ ActiveOrient.database_classes.keys # return an array of database-classnames
63
+ end
64
+
65
+ =begin
66
+ Service-Method for Model#OrientdbClass
67
+ =end
68
+
69
+ def get_db_superclass name #:nodoc:
70
+ # @actual_class_hash = get_classes( 'name', 'superClass') if @actual_class_hash.nil?
71
+ z= @actual_class_hash.find{|x,y| x['name'] == name.to_s }
72
+ z['superClass'] unless z.nil?
73
+ end
74
+
75
+ =begin
76
+ preallocate classes reads any class from the @classes-Array and allocates adequat Ruby-Objects
77
+ =end
78
+ def preallocate_classes from_model_dir= nil # :nodoc:
79
+ # always scan for E+V model-files and include
80
+ [E,V].each{|y| y.require_model_file(from_model_dir) }
81
+
82
+ ActiveOrient.database_classes.each do | db_name, the_class |
83
+ allocate_class_in_ruby( db_name ) do |detected_class|
84
+ # keep the class if it is already noted in database_classes
85
+ if [E,V].include?(detected_class) ||
86
+ ActiveOrient.database_classes.key( detected_class) ||
87
+ detected_class.require_model_file(from_model_dir) ||
88
+ ActiveOrient::Model.keep_models_without_file
89
+ true # return_value
90
+ else
91
+ logger.info{ "#{detected_class.name} --> Class NOT allocated"}
92
+ ActiveOrient.database_classes[ detected_class.ref_name ] = "no model file"
93
+ false # return_value
94
+ end
95
+ end # block
96
+ end # each iteration
97
+ end # def
98
+
99
+ end # module