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,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