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,228 +1,297 @@
1
1
  module ActiveOrient
2
- require 'active_model'
3
- #
4
- # Base class for tableless IB data Models, extends ActiveModel API
2
+
3
+
4
+ # Base class for tableless IB data Models, extends ActiveModel API
5
+
5
6
  class Base
7
+ # include OrientSupport::Logging
6
8
  extend ActiveModel::Naming
7
9
  extend ActiveModel::Callbacks
8
10
  include ActiveModel::Validations
9
11
  include ActiveModel::Serialization
10
- include ActiveModel::Serializers::Xml
12
+ # include ActiveModel::Serializers::Xml
11
13
  include ActiveModel::Serializers::JSON
12
-
14
+ include OrientDB
15
+ include Conversions # mocking ActiveModel::Conversions
16
+
17
+ mattr_accessor :logger
18
+
19
+ define_model_callbacks :initialize
20
+ # ActiveRecord::Base callback API mocks
21
+ define_model_callbacks :initialize, :only => :after
13
22
 
14
- ##Every Rest::Base-Object is stored in the @@rid_store
15
- ## The Objects are just references to the @@rid_store.
16
- ## any Change of the Object is thus synchonized to any allocated variable
17
- #
18
- @@rid_store = Hash.new
23
+ # Used to read the metadata
24
+ attr_reader :metadata
19
25
 
20
- def self.display_riid
26
+ =begin
27
+ Every Rest::Base-Object is stored in the @@rid_store
28
+ The Objects are just references to the @@rid_store.
29
+ Any Change of the Object is thus synchonized to any allocated variable.
30
+ =end
31
+ @@rid_store = Hash.new
32
+
33
+ def self.display_rid
21
34
  @@rid_store
22
35
  end
23
- def self.remove_riid obj
24
- @@rid_store[obj.riid]=nil
25
- end
26
- def self.get_riid link
27
36
 
37
+ =begin
38
+ removes an Item from the cache
39
+
40
+ obj has to provide a method #rid
41
+
42
+ thus a string or a Model-Object is accepted
43
+ =end
44
+
45
+ def self.remove_rid obj
46
+ @@rid_store.delete obj.rid if obj.rid.present?
28
47
  end
29
- def self.store_riid obj
30
- if obj.rid.present? && obj.riid.all?{|x| x.present? && x>=0} # only positive values are stored
31
- ## return the presence of a stored object as true by the block
32
- ## the block is only executed if the presence is confirmed
33
- ## Nothing is returned from the class-method
34
- if @@rid_store[obj.riid].present?
35
- yield if block_given?
36
- end
37
- @@rid_store[obj.riid] = obj
38
- @@rid_store[obj.riid] # return_value
39
- else
40
- obj # no rid-value: just return the obj
41
- end
48
+
49
+ def self.get_rid rid
50
+ rid = rid[1..-1] if rid[0]=='#'
51
+ @@rid_store[rid]
42
52
  end
43
53
 
54
+ def self.reset_rid_store
55
+ @@rid_store = Hash.new
56
+ end
44
57
 
45
- define_model_callbacks :initialize
58
+ =begin
59
+ Stores the obj in the cache.
46
60
 
47
- mattr_accessor :logger
48
- # If a opts hash is given, keys are taken as attribute names, values as data.
49
- # The model instance fields are then set automatically from the opts Hash.
50
- def initialize attributes={}, opts={}
51
- logger.progname= "ActiveOrient::Base#initialize"
52
- #possible_link_array_candidates = link_candidates = Hash.new
53
- @metadata = HashWithIndifferentAccess.new
54
- # @edges = HashWithIndifferentAccess.new
55
-
56
- run_callbacks :initialize do
57
- # puts "initialize::attributes: #{attributes.inspect}"
58
-
59
- attributes.keys.each do | att |
60
- unless att[0] == "@" # @ identifies Metadata-attributes
61
- att = att.to_sym if att.is_a?(String)
62
- unless self.class.instance_methods.detect{|x| x == att }
63
- self.class.define_property att, nil
64
- # logger.debug { "property #{att.to_s} assigned to #{self.class.to_s}" }
65
- else
66
- # logger.info{ "property #{att.to_s} NOT assigned " }
67
- end
61
+ If the cache-value exists, it is updated by the data provided in obj
62
+ and the cached obj is returned
63
+
64
+ =end
65
+ def self.store_rid obj
66
+ if obj.rid.present? && obj.rid.rid?
67
+ if @@rid_store[obj.rid].present?
68
+ @@rid_store[obj.rid].transfer_content from: obj
69
+ else
70
+ @@rid_store[obj.rid] = obj
68
71
  end
69
- end
70
-
71
- if attributes['@type'] == 'd' # document
72
- @metadata[ :type ] = attributes.delete '@type'
73
- @metadata[ :class ] = attributes.delete '@class'
74
- @metadata[ :version ] = attributes.delete '@version'
75
- @metadata[ :fieldTypes ] = attributes.delete '@fieldTypes'
76
- if attributes.has_key?( '@rid' )
77
- rid = attributes.delete '@rid'
78
- cluster, record = rid[1,rid.size].split(':')
79
- @metadata[ :cluster ] = cluster.to_i
80
- @metadata[ :record ] = record.to_i
72
+ @@rid_store[obj.rid]
73
+ else
74
+ nil
75
+ end
76
+ end
81
77
 
82
- end
83
78
 
84
- #### edges -- remove in_ and out_ and de-capitalize the remaining edge
85
- if @metadata[ :fieldTypes ].present? && (@metadata[ :fieldTypes ] =~ /=g/)
86
- edges = @metadata['fieldTypes'].split(',').find_all{|x| x=~/=g/}.map{|x| x.split('=').first}
87
- edges.each do |edge|
88
- operator, *base_edge = edge.split('_')
89
- base_edge = base_edge.join('_')
90
- unless self.class.instance_methods.detect{|x| x == base_edge }
91
- ## define two methods: out_{Edge}/{in_Edge} -> edge.
92
- self.class.define_property base_edge, nil
93
- self.class.send :alias_method, base_edge.underscore, edge #
94
- # logger.debug { "#{link}:: edge #{edge} assigned to #{self.class.to_s} and remaped to #{base_edge.underscore}" }
95
-
96
- end
97
- end
98
- end
99
- end
79
+ # rails compatibility
80
+ # remap rid to id unless id is present
81
+ # def id
82
+ # attributes[:id].present? ? attributes[:id] : rrid
83
+ # end
100
84
 
101
85
 
102
- self.attributes = attributes # set_attribute_defaults is now after_init callback
103
- end
104
- ActiveOrient::Base.store_riid self
105
- end
86
+ =begin
87
+ If a opts hash is given, keys are taken as attribute names, values as data.
88
+ The model instance fields are then set automatically from the opts Hash.
89
+ =end
106
90
 
107
- # ActiveModel API (for serialization)
91
+ def initialize attributes = {}, opts = {}
92
+ logger.progname = "ActiveOrient::Base#initialize"
93
+ @metadata = Hash.new # HashWithIndifferentAccess.new
94
+ @d = nil
95
+ run_callbacks :initialize do
96
+ if RUBY_PLATFORM == 'java' && attributes.is_a?( Document )
97
+ @d = attributes
98
+ attributes = @d.values
99
+ @metadata[:class] = @d.class_name
100
+ @metadata[:version] = @d.version
101
+ @metadata[:cluster], @metadata[:record] = @d.rid[1,@d.rid.size].split(':')
102
+ puts "Metadata: #{@metadata}"
103
+ end
104
+
105
+ # transform $current to :current and $current.mgr to :mgr
106
+ transformers = attributes.keys.map{|x| [x, x[1..-1].split(".").last.to_sym] if x[0] == '$'}.compact
107
+ # transformers: [ [original key, modified key] , [] ]
108
+ transformers.each do |a|
109
+ attributes[a.last] = attributes[a.first]
110
+ attributes.delete a.first
111
+ end
112
+
113
+ attributes.keys.each do |att|
114
+ unless att[0] == "@" # @ identifies Metadata-attributes
115
+ unless self.class.instance_methods.detect{|x| x == att.to_sym}
116
+ self.class.define_property att.to_sym, nil
117
+ else
118
+ #logger.info{"Property #{att.to_s} NOT assigned"}
119
+ end
120
+ end
121
+ end
122
+ if attributes['@type'] == 'd' # document via REST
123
+ @metadata[:type] = attributes.delete '@type'
124
+ @metadata[:class] = attributes.delete '@class'
125
+ @metadata[:version] = attributes.delete '@version'
126
+ @metadata[:fieldTypes] = attributes.delete '@fieldTypes'
127
+
128
+ if attributes.has_key?('@rid')
129
+ rid = attributes.delete '@rid'
130
+ cluster, record = rid[1 .. -1].split(':')
131
+ @metadata[:cluster] = cluster.to_i
132
+ @metadata[:record] = record.to_i
133
+ end
134
+
135
+ if @metadata[:fieldTypes ].present? && (@metadata[:fieldTypes] =~ /=g/)
136
+ @metadata[:edges] = { :in => [], :out => [] }
137
+ edges = @metadata[:fieldTypes].split(',').find_all{|x| x=~/=g/}.map{|x| x.split('=').first}
138
+ # puts "Detected EDGES: #{edges.inspect}"
139
+ edges.each do |edge|
140
+ operator, *base_edge = edge.split('_')
141
+ base_edge = base_edge.join('_')
142
+ @metadata[:edges][operator.to_sym] << base_edge
143
+ end
144
+ # unless self.class.instance_methods.detect{|x| x == base_edge}
145
+ # ## define two methods: out_{Edge}/in_{Edge} -> edge.
146
+ # self.class.define_property base_edge, nil
147
+ # allocate_edge_method = -> (edge) do
148
+ # unless (ee=db.get_db_superclass(edge)) == "E"
149
+ # allocate_edge_method[ee]
150
+ # self.class.send :alias_method, base_edge.underscore, edge
151
+ # ## define inherented classes, tooa
152
+ #
153
+
154
+ # end
155
+ # end
156
+ end
157
+ end
158
+ self.attributes = attributes # set_attribute_defaults is now after_init callback
159
+ end
160
+ # puts "Storing #{self.rid} to rid-store"
161
+ # ActiveOrient::Base.store_rid( self ) do | cache_obj|
162
+ # cache_obj.reload! self
163
+ # end
164
+ end
165
+
166
+ # ActiveModel API (for serialization)
167
+
168
+ def included_links
169
+ meta= Hash[ @metadata[:fieldTypes].split(',').map{|x| x.split '='} ]
170
+ meta.map{|x,y| x if y=='x'}.compact
171
+ end
108
172
 
109
173
  def attributes
110
- @attributes ||= HashWithIndifferentAccess.new
174
+ @attributes ||= Hash.new # WithIndifferentAccess.new
111
175
  end
112
176
 
113
177
  def attributes= attrs
114
- attrs.keys.each { |key| self.send("#{key}=", attrs[key]) }
178
+ attrs.keys.each{|key| self.send("#{key}=", attrs[key])}
115
179
  end
116
180
 
117
- # ActiveModel-style read/write_attribute accessors
118
- # Here we define the autoload mechanism
119
- def [] key
120
-
121
- iv= attributes[key.to_sym]
122
- # iv.from_orient unless iv.nil?
123
- if iv.is_a?(String) && iv.rid? #&& @metadata[:fieldTypes].present? && @metadata[:fieldTypes].include?( key.to_s+"=x" )
181
+ def my_metadata key: nil, symbol: nil
182
+ if @metadata[:fieldTypes].present?
183
+ meta= Hash[ @metadata[:fieldTypes].split(',').map{|x| x.split '='} ]
184
+ if key.present?
185
+ meta[key.to_s]
186
+ elsif symbol.present?
187
+ meta.map{|x,y| x if y == symbol.to_s }.compact
188
+ else
189
+ meta
190
+ end
191
+ end
192
+ end
124
193
 
194
+ =begin
195
+ ActiveModel-style read/write_attribute accessors
125
196
 
126
- # puts "autoload: #{iv}"
127
- ActiveOrient::Model.autoload_object iv
128
- elsif iv.is_a?(Array) # && @metadata[:fieldTypes].present? && @metadata[:fieldTypes].match( key.to_s+"=[znmgx]" )
129
- # puts "autoload: #{iv.inspect}"
130
- OrientSupport::Array.new self, *iv.map{|y| (y.is_a?(String) && y.rid?) ? ActiveOrient::Model.autoload_object( y ) : y }
131
- else
197
+ Autoload mechanism and data conversion are defined in the method "from_orient" of each class
198
+ =end
132
199
 
133
- if @metadata[:fieldTypes].present? && @metadata[:fieldTypes].include?( key.to_s+"=t" ) # time
134
- # switch between date and datetime representation of the date-object
135
- iv =~ /00:00:00/ ? Date.parse( iv ) : DateTime.parse( iv )
136
- else
137
- iv
138
- end
139
- end
140
- end
200
+ def [] key
201
+
202
+ iv = attributes[key]
203
+ if my_metadata( key: key) == "t"
204
+ iv =~ /00:00:00/ ? Date.parse(iv) : DateTime.parse(iv)
205
+ elsif my_metadata( key: key) == "x"
206
+ iv = ActiveOrient::Model.autoload_object iv
207
+ elsif iv.is_a? Array
208
+ OrientSupport::Array.new( work_on: self, work_with: iv.from_orient){ key.to_sym }
209
+ elsif iv.is_a? Hash
210
+ # if iv.keys.include?("@class" )
211
+ # ActiveOrient::Model.orientdb_class( name: iv["@class"] ).new iv
212
+ # else
213
+ # iv
214
+ OrientSupport::Hash.new( self, iv.from_orient){ key.to_sym }
215
+ # end
216
+ # elsif iv.is_a? RecordMap
217
+ # iv
218
+ # puts "RecordSet detected"
219
+ else
220
+ iv.from_orient
221
+ end
222
+ end
223
+
224
+ def []= key, val
225
+ val = val.rid if val.is_a?( ActiveOrient::Model ) && val.rid.rid?
226
+ attributes[key.to_sym] = case val
227
+ when Array
228
+ if val.first.is_a?(Hash)
229
+ v = val.map{ |x| x }
230
+ OrientSupport::Array.new(work_on: self, work_with: v )
231
+ else
232
+ OrientSupport::Array.new(work_on: self, work_with: val )
233
+ end
234
+ when Hash
235
+ if val.keys.include?("@class" )
236
+ OrientSupport::Array.new( work_on: self, work_with: val.from_orient){ key.to_sym }
237
+ else
238
+ OrientSupport::Hash.new( self, val )
239
+ end
240
+ else
241
+ val
242
+ end
243
+ end
141
244
 
142
245
  def update_attribute key, value
143
246
  @attributes[key] = value
144
247
  end
145
- =begin
146
- Here we define how the attributes are initialized
147
- Key and val are set by the RestCliend
148
- =end
149
- def []= key, val
150
- val = val.rid if val.is_a? ActiveOrient::Model
151
- # if val.is_a?(Array) # && @metadata[:fieldTypes].present? && @metadata[:fieldTypes].include?( key.to_s+"=n" )
152
- # if @metadata[ :fieldTypes ] =~ /out=x,in=x/
153
- # puts "VAL is a ARRAY"
154
- # else
155
- # puts "METADATA: #{ @metadata[ :fieldTypes ]} "
156
- # end
157
- # val# = val.map{|x| if val.is_a? ActiveOrient::Model then val.rid else val end }
158
- # end
159
- attributes[key.to_sym] = case val
160
- when Array
161
- if val.first.is_a?(Hash)
162
- v=val.map do |x|
163
- if x.is_a?( Hash )
164
- HashWithIndifferentAccess.new(x)
165
- else
166
- x
167
- end
168
- end
169
- OrientSupport::Array.new( self, *v )
170
- else
171
- OrientSupport::Array.new( self, *val )
172
- end
173
- when Hash
174
- HashWithIndifferentAccess.new(val)
175
- else
176
- val
177
- end
178
-
179
- end
180
-
181
- def to_model
248
+
249
+ def to_model # :nodoc:
182
250
  self
183
251
  end
184
252
 
253
+ # Noop methods mocking ActiveRecord::Base macros
185
254
 
186
-
187
- ### Noop methods mocking ActiveRecord::Base macros
188
-
189
255
  def self.attr_protected *args
190
256
  end
191
257
 
192
258
  def self.attr_accessible *args
193
259
  end
194
260
 
195
- ### ActiveRecord::Base association API mocks
196
-
197
- def self.belongs_to model, *args
261
+ # ActiveRecord::Base association API mocks
262
+ #
263
+ def self.belongs_to model, *args # :nodoc:
198
264
  attr_accessor model
199
265
  end
200
-
201
- def self.has_one model, *args
266
+ #
267
+ def self.has_one model, *args # :nodoc:
202
268
  attr_accessor model
203
269
  end
204
-
205
- def self.has_many models, *args
270
+ #
271
+ def self.has_many models, *args # :nodoc:
206
272
  attr_accessor models
207
-
208
273
  define_method(models) do
209
- self.instance_variable_get("@#{models}") ||
210
- self.instance_variable_set("@#{models}", [])
274
+ self.instance_variable_get("@#{models}") || self.instance_variable_set("@#{models}", [])
211
275
  end
212
276
  end
213
-
214
- def self.find *args
215
- []
277
+ #
278
+ # def self.find *args
279
+ # []
280
+ # end
281
+ #
282
+ =begin
283
+ Exclude some properties from loading via get, reload!, get_document, get_record
284
+ =end
285
+ def self.exclude_the_following_properties *args
286
+ puts "excluding #{args}"
287
+ @excluded = (@excluded.is_a?( Array))? @excluded + args : args
288
+ puts "#{self.inspect} --> excluded #{@excluded}"
216
289
  end
217
290
 
218
- ### ActiveRecord::Base callback API mocks
219
-
220
- define_model_callbacks :initialize, :only => :after
221
-
222
- ### ActiveRecord::Base misc
223
-
224
- def self.serialize *properties
291
+ # ActiveRecord::Base misc
292
+ def self.serialize *properties # :nodoc:
225
293
  end
226
-
294
+ # Enable lazy loading
295
+ ActiveSupport.run_load_hooks(:active_orient, self)
227
296
  end # Model
228
- end # module
297
+ end # module