active-orient 0.4 → 0.80

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