active-orient 0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/Gemfile +16 -0
- data/Guardfile +21 -0
- data/LICENSE +22 -0
- data/README.md +275 -0
- data/acitve-orient.gemspec +27 -0
- data/config/boot.rb +24 -0
- data/config/connect.yml +13 -0
- data/lib/base.rb +220 -0
- data/lib/base_properties.rb +147 -0
- data/lib/model.rb +441 -0
- data/lib/orient.rb +98 -0
- data/lib/query.rb +88 -0
- data/lib/rest.rb +942 -0
- data/lib/support.rb +315 -0
- data/test.rb +4 -0
- data/usecase.md +91 -0
- metadata +104 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_support/hash_with_indifferent_access'
|
4
|
+
|
5
|
+
module ActiveOrient
|
6
|
+
|
7
|
+
# Module adds prop Macro and
|
8
|
+
module BaseProperties
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
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)
|
26
|
+
end]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Update nil attributes from given Hash or model
|
30
|
+
def update_missing attrs
|
31
|
+
attrs = attrs.content_attributes unless attrs.kind_of?(Hash)
|
32
|
+
|
33
|
+
attrs.each { |attr, val| send "#{attr}=", val if send(attr).blank? }
|
34
|
+
self # for chaining
|
35
|
+
end
|
36
|
+
|
37
|
+
# Default Model comparison
|
38
|
+
def == other
|
39
|
+
case other
|
40
|
+
when String # Probably a link or a rid
|
41
|
+
link == other || rid == other
|
42
|
+
else
|
43
|
+
content_attributes.keys.inject(true) { |res, key|
|
44
|
+
res && other.respond_to?(key) && (send(key) == other.send(key)) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
### Default attributes support
|
49
|
+
|
50
|
+
def default_attributes
|
51
|
+
{:created_at => Time.now,
|
52
|
+
:updated_at => Time.now,
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_attribute_defaults
|
57
|
+
default_attributes.each do |key, val|
|
58
|
+
self.send("#{key}=", val) if self.send(key).nil?
|
59
|
+
# self.send("#{key}=", val) if self[key].nil? # Problems with association defaults
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
included do
|
64
|
+
|
65
|
+
after_initialize :set_attribute_defaults
|
66
|
+
|
67
|
+
### Class macros
|
68
|
+
|
69
|
+
def self.prop *properties
|
70
|
+
prop_hash = properties.last.is_a?(Hash) ? properties.pop : {}
|
71
|
+
|
72
|
+
properties.each { |names| define_property names, nil }
|
73
|
+
prop_hash.each { |names, type| define_property names, type }
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.define_property names, body
|
77
|
+
aliases = [names].flatten
|
78
|
+
name = aliases.shift
|
79
|
+
instance_eval do
|
80
|
+
|
81
|
+
define_property_methods name, body
|
82
|
+
|
83
|
+
aliases.each do |ali|
|
84
|
+
alias_method "#{ali}", name
|
85
|
+
alias_method "#{ali}=", "#{name}="
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.define_property_methods name, body={}
|
91
|
+
#p name, body
|
92
|
+
case body
|
93
|
+
when '' # default getter and setter
|
94
|
+
define_property_methods name
|
95
|
+
|
96
|
+
when Array # [setter, getter, validators]
|
97
|
+
define_property_methods name,
|
98
|
+
:get => body[0],
|
99
|
+
:set => body[1],
|
100
|
+
:validate => body[2]
|
101
|
+
|
102
|
+
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
|
122
|
+
|
123
|
+
# Define validator(s)
|
124
|
+
[body[:validate]].flatten.compact.each do |validator|
|
125
|
+
case validator
|
126
|
+
when Proc
|
127
|
+
validates_each name, &validator
|
128
|
+
when Hash
|
129
|
+
validates name, validator.dup
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# TODO define self[:name] accessors for :virtual and :flag properties
|
134
|
+
|
135
|
+
else # setter given
|
136
|
+
define_property_methods name, :set => body, :get => body
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Timestamps in lightweight models
|
141
|
+
unless defined?(ActiveRecord::Base) && ancestors.include?(ActiveRecord::Base)
|
142
|
+
prop :created_at, :updated_at
|
143
|
+
end
|
144
|
+
|
145
|
+
end # included
|
146
|
+
end # module BaseProperties
|
147
|
+
end
|
data/lib/model.rb
ADDED
@@ -0,0 +1,441 @@
|
|
1
|
+
class String
|
2
|
+
def to_or
|
3
|
+
"'#{self}'"
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Numeric
|
8
|
+
def to_or
|
9
|
+
"#{self.to_s}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
module ActiveOrient
|
13
|
+
|
14
|
+
#require 'base'
|
15
|
+
#require 'base_properties'
|
16
|
+
|
17
|
+
class Model < ActiveOrient::Base
|
18
|
+
include BaseProperties
|
19
|
+
|
20
|
+
mattr_accessor :orientdb
|
21
|
+
mattr_accessor :logger
|
22
|
+
=begin
|
23
|
+
orientdb_class is used to instantiate a ActiveOrient:Model:{class} by providing its name
|
24
|
+
todo: implement object-inherence
|
25
|
+
=end
|
26
|
+
def self.orientdb_class name:
|
27
|
+
klass = Class.new( self )
|
28
|
+
name = name.to_s.camelize
|
29
|
+
if self.send :const_defined?, name
|
30
|
+
retrieved_class = self.send :const_get, name
|
31
|
+
else
|
32
|
+
new_class = self.send :const_set , name , klass
|
33
|
+
new_class.orientdb = orientdb
|
34
|
+
new_class # return_value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
=begin
|
39
|
+
ActiveOrient::Model.autoload_object "#00:00"
|
40
|
+
either retrieves the object from the rid_store or loads it from the DB
|
41
|
+
|
42
|
+
the rid_store is updated!
|
43
|
+
|
44
|
+
to_do: fetch for version in the db and load the object if a change is detected
|
45
|
+
=end
|
46
|
+
def self.autoload_object link
|
47
|
+
# puts "autoload_object #{link}"
|
48
|
+
link_cluster_and_record = link[1,link.size].split(':').map &:to_i
|
49
|
+
@@rid_store[link_cluster_and_record].presence || orientdb.get_document( link )
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def self.superClass
|
54
|
+
orientdb.get_classes( 'name', 'superClass').detect{|x| x["name"].downcase == new.class.to_s.downcase.split(':')[-1].to_s
|
55
|
+
}['superClass']
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_orient
|
59
|
+
link
|
60
|
+
end
|
61
|
+
def from_orient
|
62
|
+
self
|
63
|
+
end
|
64
|
+
=begin
|
65
|
+
Returns just the name of the Class
|
66
|
+
=end
|
67
|
+
def classname
|
68
|
+
self.class.to_s.split(':')[-1]
|
69
|
+
end
|
70
|
+
|
71
|
+
=begin
|
72
|
+
If a Rest::Model-Object is included in a HashWidhtIndifferentAccess-Object, only the link is stored
|
73
|
+
=end
|
74
|
+
def nested_under_indifferent_access # :nodoc:
|
75
|
+
link
|
76
|
+
end
|
77
|
+
|
78
|
+
# hard-coded orientdb-columns
|
79
|
+
# prop :cluster, :version, :record, :fieldtypes
|
80
|
+
|
81
|
+
# def default_attributes
|
82
|
+
# super.merge cluster: 0
|
83
|
+
# super.merge version: 0
|
84
|
+
# super.merge record: 0
|
85
|
+
# end
|
86
|
+
def riid # :nodoc:
|
87
|
+
[ @metadata[ :cluster ] , @metadata[ :record ] ]
|
88
|
+
end
|
89
|
+
=begin
|
90
|
+
rid is used in the where-part of sql-queries
|
91
|
+
=end
|
92
|
+
def rid
|
93
|
+
if @metadata.has_key?( 'cluster')
|
94
|
+
"#{@metadata[ :cluster ]}:#{@metadata[ :record ]}"
|
95
|
+
else
|
96
|
+
"0:0"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
=begin
|
100
|
+
link is used in any sql-commands
|
101
|
+
eg . update #link set ...
|
102
|
+
=end
|
103
|
+
def link
|
104
|
+
"##{rid}"
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def method_missing method, *args, &b
|
109
|
+
property= orientdb.get_class_properties( classname )['properties'].detect{|x| x.has_value? method.to_s }
|
110
|
+
puts "method_missing::property"
|
111
|
+
puts property.inspect
|
112
|
+
if property.present?
|
113
|
+
if property['type'] == 'LINKSET'
|
114
|
+
attributes[method] = OrientSupport::Array.new( self )
|
115
|
+
else
|
116
|
+
attributes[method] = ''
|
117
|
+
end
|
118
|
+
else
|
119
|
+
raise NoMethodError
|
120
|
+
end
|
121
|
+
end
|
122
|
+
=begin
|
123
|
+
Queries the database and fetches the count of datasets
|
124
|
+
|
125
|
+
Any parameter that qualifies a database-query is suppoerted
|
126
|
+
(see method get_documents)
|
127
|
+
=end
|
128
|
+
def self.count **args
|
129
|
+
orientdb.count_documents from: self , **args
|
130
|
+
end
|
131
|
+
=begin
|
132
|
+
Creates a new Instance of the Class with the applied attributes
|
133
|
+
and returns the freshly instantiated Object
|
134
|
+
=end
|
135
|
+
|
136
|
+
def self.create properties = {}
|
137
|
+
orientdb.create_or_update_document self, set: properties
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.update_or_create set: {}, where:{} ,**args, &b
|
141
|
+
orientdb.update_or_create_documents self , set: set, where: where , **args , &b
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
# historic method
|
146
|
+
def self.new_document attributes: {} # :nodoc:
|
147
|
+
orientdb.create_or_update_document self, set: attributes
|
148
|
+
end
|
149
|
+
=begin
|
150
|
+
Create a Property in the Schema of the Class
|
151
|
+
:call-seq:
|
152
|
+
self.create_property field (required) , type: 'string', linked_class: nil
|
153
|
+
=end
|
154
|
+
|
155
|
+
def self.create_property field, **keyword_arguments
|
156
|
+
orientdb.create_property self, field, **keyword_arguments
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.create_link name, class_name
|
160
|
+
orientdb.create_property self, name, type: 'link', linked_class: class_name
|
161
|
+
end
|
162
|
+
def self.create_linkset name, class_name
|
163
|
+
orientdb.create_property self, name, type: 'linkset', linked_class: class_name
|
164
|
+
end
|
165
|
+
=begin
|
166
|
+
Only if the Class inherents from »E«
|
167
|
+
Instantiate a new Edge betwen two Vertices
|
168
|
+
|
169
|
+
Parameter: unique: (true) In case of an existing Edge just update its Properties.
|
170
|
+
:call-seq:
|
171
|
+
self.create_edge from: , to: , unique: false, attributes:{}
|
172
|
+
=end
|
173
|
+
def self.create_edge **keyword_arguments
|
174
|
+
o=orientdb.nexus_edge self, **keyword_arguments
|
175
|
+
[:from,:to].each{|y| keyword_arguments[y].reload! }
|
176
|
+
o # return_value
|
177
|
+
end
|
178
|
+
|
179
|
+
def query q
|
180
|
+
a= ActiveOrient::Query.new
|
181
|
+
a.queries << q
|
182
|
+
a.execute_queries
|
183
|
+
end
|
184
|
+
=begin
|
185
|
+
Parameter projection:
|
186
|
+
|
187
|
+
»select« is a method of enumeration, we use »projection:« to specify anything between »select« and »from«
|
188
|
+
in the query-string.
|
189
|
+
|
190
|
+
projection: a_string --> inserts the sting as it appears
|
191
|
+
an OrientSupport::OrientQuery-Object --> performs a sub-query and uses the result for further querying though the given parameters.
|
192
|
+
|
193
|
+
[ a, b, c ] --> "a , b , c " ( inserts a comma-separated list )
|
194
|
+
|
195
|
+
{ a: b, "sum(x) "=> f } --> "a as b, sum(x) as f" (renames properties and uses functions )
|
196
|
+
Parameter distinct:
|
197
|
+
|
198
|
+
Performs a Query like » select distinct( property ) [ as property ] from ...«
|
199
|
+
|
200
|
+
distinct: :property --> the result is mapped to the property »distinct«.
|
201
|
+
|
202
|
+
[ :property ] --> the result replaces the property
|
203
|
+
|
204
|
+
{ property: :some_name} --> the result is mapped to ModelInstance.some_name
|
205
|
+
|
206
|
+
Parameter Order
|
207
|
+
|
208
|
+
Sorts the result-set.
|
209
|
+
|
210
|
+
If new properties are introduced via select:, distinct: etc
|
211
|
+
|
212
|
+
Sorting takes place on these properties
|
213
|
+
|
214
|
+
order: :property
|
215
|
+
{ property: asc, property: desc }
|
216
|
+
[property, property, .. ] ( orderdirection is 'asc' )
|
217
|
+
|
218
|
+
|
219
|
+
Further supported Parameter:
|
220
|
+
group_by
|
221
|
+
skip
|
222
|
+
limit
|
223
|
+
unwind
|
224
|
+
|
225
|
+
see orientdb- documentation (https://orientdb.com/docs/last/SQL-Query.html)
|
226
|
+
|
227
|
+
Parameter query:
|
228
|
+
Instead of providing the parameter, the OrientSupport::OrientQuery can build and
|
229
|
+
tested before the method-call. The OrientQuery-Object can be provided with the query-parameter
|
230
|
+
i.e.
|
231
|
+
q= OrientSupport::OrientQuery.new
|
232
|
+
TestModel = r.open_class 'test_model'
|
233
|
+
q.from TestModel
|
234
|
+
q.where { name: 'Thomas' }
|
235
|
+
|
236
|
+
count= TestModel.count query:q
|
237
|
+
q.limit 10
|
238
|
+
0.step(count,10) do |x|
|
239
|
+
q.skip = x
|
240
|
+
puts TestModel.get_documents( query: q ).map{|x| x.adress }.join('\t')
|
241
|
+
end
|
242
|
+
prints a Table with 10 columns.
|
243
|
+
=end
|
244
|
+
|
245
|
+
def self.get_documents **args , &b
|
246
|
+
orientdb.get_documents from: classname, **args, &b
|
247
|
+
|
248
|
+
end
|
249
|
+
=begin
|
250
|
+
Performs a query on the Class and returns an Array of ActiveOrient:Model-Records.
|
251
|
+
|
252
|
+
Example:
|
253
|
+
Log = r.open_class 'Log'
|
254
|
+
Log.where priority: 'high'
|
255
|
+
--> submited database-request: query/hc_database/sql/select from Log where priority = 'high'/-1
|
256
|
+
=> [ #<ActiveOrient::Model::Log:0x0000000480f7d8 @metadata={ ... }, ... ]
|
257
|
+
|
258
|
+
|
259
|
+
=end
|
260
|
+
def self.where attributes = {}
|
261
|
+
orientdb.get_documents from: self, where: attributes
|
262
|
+
end
|
263
|
+
=begin
|
264
|
+
|
265
|
+
removes the Model-Instance from the database
|
266
|
+
|
267
|
+
returns true (successfully deleted) or false ( obj not deleted)
|
268
|
+
=end
|
269
|
+
def delete
|
270
|
+
|
271
|
+
r= if is_edge?
|
272
|
+
# returns the count of deleted edges
|
273
|
+
orientdb.delete_edge rid
|
274
|
+
else
|
275
|
+
orientdb.delete_document rid
|
276
|
+
end
|
277
|
+
ActiveOrient::Base.remove_riid self if r # removes the obj from the rid_store
|
278
|
+
r # true or false
|
279
|
+
end
|
280
|
+
=begin
|
281
|
+
An Edge is defined
|
282
|
+
* when inherented from the superclass »E» (formal definition)
|
283
|
+
* if it has an in- and an out property
|
284
|
+
|
285
|
+
Actually we just check the second term as we trust the constuctor to work properly
|
286
|
+
=end
|
287
|
+
def is_edge?
|
288
|
+
attributes.keys.include?( 'in') && attributes.keys.include?('out')
|
289
|
+
end
|
290
|
+
# get enables loading of datasets if a link is followed
|
291
|
+
# model_class.all.first.link.get
|
292
|
+
def self.get rid
|
293
|
+
orientdb.get_document rid
|
294
|
+
end
|
295
|
+
def self.all
|
296
|
+
orientdb.get_documents from: self
|
297
|
+
end
|
298
|
+
def self.first where: {}
|
299
|
+
orientdb.get_documents( from: self, where: where, limit: 1).pop
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.last where: {}
|
303
|
+
# debug:: orientdb.get_documents( self, order: { "@rid" => 'desc' }, limit: 1 ){ |x| puts x }.pop
|
304
|
+
orientdb.get_documents( from: self, where: where, order: { "@rid" => 'desc' }, limit: 1 ).pop
|
305
|
+
end
|
306
|
+
=begin
|
307
|
+
Convient update of the dataset by calling sql-patch
|
308
|
+
The attributes are saved to the database.
|
309
|
+
With the optional :set argument ad-hoc attributes can be defined
|
310
|
+
obj = ActiveOrient::Model::Contracts.first
|
311
|
+
obj.name = 'new_name'
|
312
|
+
obj.update set: { yesterdays_event: 35 }
|
313
|
+
=end
|
314
|
+
def update set: {}
|
315
|
+
attributes.merge!( set ) if set.present?
|
316
|
+
result= orientdb.patch_document(rid) do
|
317
|
+
attributes.merge( { '@version' => @metadata[ :version ], '@class' => @metadata[ :class ] } )
|
318
|
+
end
|
319
|
+
# returns a new instance of ActiveOrient::Model
|
320
|
+
reload! ActiveOrient::Model.orientdb_class(name: classname).new( JSON.parse( result ))
|
321
|
+
# instantiate object, update rid_store and reassign to self
|
322
|
+
|
323
|
+
end
|
324
|
+
=begin
|
325
|
+
Overwrite the attributes with Database-Contents (or attributes provided by the updated_dataset.model-instance)
|
326
|
+
=end
|
327
|
+
def reload! updated_dataset=nil
|
328
|
+
updated_dataset = orientdb.get_document( link) if updated_dataset.nil?
|
329
|
+
@metadata[:version]= updated_dataset.version
|
330
|
+
attributes = updated_dataset.attributes
|
331
|
+
self # return_value (otherwise only the attributes would be returned)
|
332
|
+
end
|
333
|
+
|
334
|
+
def remove_item_from_property array, item=nil
|
335
|
+
logger.progname = 'ActiveOrient::Model#RemoveItemFromProperty'
|
336
|
+
execute_array = Array.new
|
337
|
+
return unless attributes.has_key? array
|
338
|
+
remove_execute_array = -> (it) do
|
339
|
+
case it
|
340
|
+
when ActiveOrient::Model
|
341
|
+
execute_array << {type: "cmd", language: "sql", command: "update #{link} remove #{array} = #{it.link}"}
|
342
|
+
when String
|
343
|
+
execute_array << {type: "cmd", language: "sql", command: "update #{link} remove #{array} = '#{it}'"}
|
344
|
+
when Numeric
|
345
|
+
execute_array << {type: "cmd", language: "sql", command: "update #{link} remove #{array} = #{it}"}
|
346
|
+
else
|
347
|
+
logger.error { "Only Basic Formats supported . Cannot Serialize #{it.class} this way" }
|
348
|
+
logger.error { "Try to load the array from the DB, modify it and update the hole record" }
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
if block_given?
|
353
|
+
items = yield
|
354
|
+
items.each{|x| remove_execute_array[x]; self.attributes[array].delete( x ) }
|
355
|
+
elsif item.present?
|
356
|
+
remove_execute_array[item]
|
357
|
+
a= attributes; a.delete item
|
358
|
+
self.attributes[array].delete( item )
|
359
|
+
end
|
360
|
+
orientdb.execute do
|
361
|
+
execute_array
|
362
|
+
end
|
363
|
+
reload!
|
364
|
+
|
365
|
+
rescue RestClient::InternalServerError => e
|
366
|
+
logger.error " Could not remove item in #{array} "
|
367
|
+
logger.error e.inspect
|
368
|
+
end
|
369
|
+
|
370
|
+
=begin
|
371
|
+
Convient method for populating embedded- or linkset-properties
|
372
|
+
|
373
|
+
In both cases an array/ a collection is stored in the database.
|
374
|
+
|
375
|
+
its called via
|
376
|
+
model.add_item_to_property( linkset- or embedded property, Object_to_be_linked_to )
|
377
|
+
or
|
378
|
+
mode.add_items_to_property( linkset- or embedded property ) do
|
379
|
+
Array_of_Objects_to_be_linked_to
|
380
|
+
(actually, the objects must inherent from ActiveOrient::Model, Numeric, String)
|
381
|
+
end
|
382
|
+
|
383
|
+
to_do: use "<<" to add the item to the property
|
384
|
+
=end
|
385
|
+
def add_item_to_property array, item=nil
|
386
|
+
logger.progname = 'ActiveOrient::Model#AddItem2Property'
|
387
|
+
execute_array = Array.new
|
388
|
+
self.attributes[array] = Array.new unless attributes[array].present?
|
389
|
+
add_2_execute_array = -> (it) do
|
390
|
+
case it
|
391
|
+
when ActiveOrient::Model
|
392
|
+
execute_array << {type: "cmd", language: "sql", command: "update #{link} add #{array} = #{it.link}"}
|
393
|
+
when String
|
394
|
+
execute_array << {type: "cmd", language: "sql", command: "update #{link} add #{array} = '#{it}'"}
|
395
|
+
when Numeric
|
396
|
+
execute_array << {type: "cmd", language: "sql", command: "update #{link} add #{array} = #{it}"}
|
397
|
+
else
|
398
|
+
logger.error { "Only Basic Formats supported . Cannot Serialize #{it.class} this way" }
|
399
|
+
logger.error { "Try to load the array from the DB, modify it and update the hole record" }
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
if block_given?
|
404
|
+
items = yield
|
405
|
+
items.each{|x| add_2_execute_array[x]; self.attributes[array] << x }
|
406
|
+
elsif item.present?
|
407
|
+
add_2_execute_array[item]
|
408
|
+
self.attributes[array] << item
|
409
|
+
end
|
410
|
+
orientdb.execute do
|
411
|
+
execute_array
|
412
|
+
end
|
413
|
+
reload!
|
414
|
+
|
415
|
+
rescue RestClient::InternalServerError => e
|
416
|
+
logger.error " Duplicate found in #{array} "
|
417
|
+
logger.error e.inspect
|
418
|
+
end
|
419
|
+
|
420
|
+
alias add_items_to_property add_item_to_property
|
421
|
+
## historical aliases
|
422
|
+
alias update_linkset add_item_to_property
|
423
|
+
alias update_embedded add_item_to_property
|
424
|
+
=begin
|
425
|
+
Convient method for updating a linkset-property
|
426
|
+
its called via
|
427
|
+
model.update_linkset( linkset-property, Object_to_be_linked_to )
|
428
|
+
or
|
429
|
+
mode.update_linkset( linkset-property ) do
|
430
|
+
Array_of_Objects_to_be_linked_to
|
431
|
+
end
|
432
|
+
=end
|
433
|
+
|
434
|
+
#private
|
435
|
+
def version
|
436
|
+
@metadata[ :version ]
|
437
|
+
end
|
438
|
+
|
439
|
+
end # class
|
440
|
+
|
441
|
+
end # module
|