active-orient 0.6 → 0.42

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 +4 -4
  2. data/.gitignore +0 -1
  3. data/Gemfile +4 -10
  4. data/Guardfile +4 -12
  5. data/README.md +198 -261
  6. data/VERSION +1 -1
  7. data/active-orient-0.4.gem +0 -0
  8. data/active-orient-0.41.gem +0 -0
  9. data/active-orient.gemspec +5 -6
  10. data/config/boot.rb +0 -84
  11. data/config/connect.yml +4 -8
  12. data/examples/books.rb +39 -86
  13. data/examples/streets.rb +84 -85
  14. data/lib/active-orient.rb +9 -57
  15. data/lib/base.rb +145 -172
  16. data/lib/base_properties.rb +44 -40
  17. data/lib/model.rb +468 -0
  18. data/lib/orient.rb +60 -114
  19. data/lib/query.rb +73 -71
  20. data/lib/rest.rb +1059 -0
  21. data/lib/support.rb +319 -386
  22. data/test.rb +4 -0
  23. data/usecase.md +91 -0
  24. metadata +20 -65
  25. data/bin/active-orient-console +0 -38
  26. data/config/config.yml +0 -10
  27. data/create_project +0 -19
  28. data/examples/test_commands.rb +0 -92
  29. data/examples/test_commands_2.rb +0 -54
  30. data/examples/test_commands_3.rb +0 -48
  31. data/examples/test_commands_4.rb +0 -28
  32. data/examples/time_graph.md +0 -162
  33. data/gratefuldeadconcerts.md +0 -94
  34. data/lib/class_utils.rb +0 -300
  35. data/lib/database_utils.rb +0 -106
  36. data/lib/init.rb +0 -45
  37. data/lib/java-api.rb +0 -437
  38. data/lib/jdbc.rb +0 -211
  39. data/lib/model/edge.rb +0 -55
  40. data/lib/model/model.rb +0 -91
  41. data/lib/model/the_class.rb +0 -500
  42. data/lib/model/the_record.rb +0 -322
  43. data/lib/model/vertex.rb +0 -136
  44. data/lib/orientdb_private.rb +0 -48
  45. data/lib/other.rb +0 -330
  46. data/lib/rest/change.rb +0 -137
  47. data/lib/rest/create.rb +0 -488
  48. data/lib/rest/delete.rb +0 -134
  49. data/lib/rest/operations.rb +0 -160
  50. data/lib/rest/read.rb +0 -150
  51. data/lib/rest/rest.rb +0 -112
  52. data/lib/rest_disabled.rb +0 -24
  53. data/linkmap.md +0 -75
  54. data/namespace.md +0 -111
  55. data/old_lib_functions/two_general_class.rb +0 -139
  56. data/rails.md +0 -125
  57. data/rails/activeorient.rb +0 -53
  58. data/rails/config.yml +0 -10
  59. data/rails/connect.yml +0 -17
  60. data/usecase_oo.md +0 -61
@@ -1,488 +0,0 @@
1
- module RestCreate
2
-
3
- ######### DATABASE ##########
4
-
5
- =begin
6
- Creates a database with the given name and switches to this database as working-database. Types are either 'plocal' or 'memory'
7
-
8
- Returns the name of the working-database
9
- =end
10
-
11
- def create_database type: 'plocal', database:
12
- logger.progname = 'RestCreate#CreateDatabase'
13
- old_d = ActiveOrient.database
14
- ActiveOrient.database_classes = []
15
- ActiveOrient.database = database
16
- begin
17
- response = @res["database/#{ActiveOrient.database}/#{type}"].post ""
18
- if response.code == 200
19
- logger.info{"Database #{ActiveOrient.database} successfully created and stored as working database"}
20
- else
21
- logger.error{"Database #{ActiveOrient.database} was NOT created. Working Database is still #{ActiveOrient.database}"}
22
- ActiveOrient.database = old_d
23
- end
24
- rescue RestClient::InternalServerError => e
25
- logger.error{"Database #{ActiveOrient.database} was NOT created. Working Database is still #{ActiveOrient.database}"}
26
- ActiveOrient.database = old_d
27
- end
28
- ActiveOrient.database # return_value
29
- end
30
-
31
- ######### CLASS ##########
32
- =begin
33
- Creates classes and class-hierarchies in OrientDB and in Ruby.
34
- Takes a String, Array or Hash as argument and returns a (nested) Array of
35
- successfull allocated Ruby-Classes.
36
- If a block is provided, this is used to allocate the class to this superclass.
37
-
38
- Examples
39
-
40
- create_class "a_single_class"
41
- create_class :a_single_class
42
- create_class( :a_single_class ){ :a_super_class }
43
- create_class( :a_single_class ){ superclass: :a_super_class, abstract: true }
44
- create_class( ["c",:l,:A,:SS] ){ :V } --> vertices
45
- create_class( ["c",:l,:A,:SS] ){ superclass: :V, abstract: true } --> abstract vertices
46
- create_class( { V: [ :A, :B, C: [:c1,:c3,:c2] ], E: [:has_content, :becomes_hot ]} )
47
- =end
48
-
49
-
50
- =begin
51
- General method to create database classes
52
-
53
- Accepts
54
- * a string or symbol
55
-
56
- creates a single class and returns the ActiveOrient::Model-Class
57
- * an arrray of strings or symbols
58
-
59
- creates alltogether and returns an array of created ActiveOrient::Model-Classes
60
- * a (nested) Hash
61
-
62
- then creates a hierarchy of database-classes and returns them as hash
63
-
64
- takes an optional block to specify a superclass. This class MUST exist.
65
-
66
-
67
- eg.
68
- create_classes( :test ){ :V }
69
-
70
- creates a vertex-class, returns just Test ( < ActiveOrient::Model)
71
-
72
- a,b,c = create_classes( :test1, :test2, test3 ) { :V }
73
-
74
- creates three vertex-classes and assigns them to var's a,b, and c
75
-
76
- create_classes( test: [:test1, :test2, test3] ) { :V }
77
-
78
- creates a vertex-class Test and three clild-classes
79
-
80
- create_classes( :V => :test)
81
-
82
- creates a vertex-class, too, returns the Hash
83
-
84
- #todo
85
- #check if a similar classname already exists --> Contract == contract == conTract
86
- #and assign to this existing one.
87
- =end
88
- def create_classes *classes, &b
89
- return if classes.empty?
90
-
91
- classes = classes.pop if classes.size == 1
92
- consts = allocate_classes_in_ruby( classes , &b )
93
- all_classes = consts.is_a?( Array) ? consts.flatten : [consts]
94
- dc = database_classes(requery: true)
95
- selected_classes = all_classes.map do | this_class |
96
- this_class unless dc.include?( this_class.ref_name ) rescue nil
97
- end.compact.uniq
98
-
99
- command= selected_classes.map do | database_class |
100
- ## improper initialized ActiveOrient::Model-classes lack a ref_name class-variable
101
- if database_class.ref_name.blank?
102
- logger.error{ "Improper initialized ActiveOrient::Model #{database_class}" }
103
- raise ArgumentError
104
- end
105
- database_class.require_model_file
106
- c = if database_class.superclass == ActiveOrient::Model || database_class.superclass.ref_name.blank?
107
- "CREATE CLASS #{database_class.ref_name}"
108
- else
109
- "CREATE CLASS #{database_class.ref_name} EXTENDS #{database_class.superclass.ref_name}"
110
- end
111
- c << " ABSTRACT" if database_class.abstract
112
- { type: "cmd", language: 'sql', command: c } # return value 4 command
113
- end
114
- # execute anything as batch, don't roll back in case of an error
115
-
116
- execute transaction: false, tolerated_error_code: /already exists in current database/ do
117
- command
118
- end
119
- # update the internal class hierarchy
120
- database_classes requery: true
121
- # return all allocated classes, no matter whether they had to be created in the DB or not.
122
- # keep the format of the input-parameter
123
- #consts.shift if block_given? && consts.is_a?( Array) # remove the first element
124
- # remove traces of superclass-allocations
125
- if classes.is_a? Hash
126
- consts = Hash[ consts ]
127
- consts.each_key{ |x| consts[x].delete_if{|y| y == x} if consts[x].is_a? Array }
128
- end
129
- consts
130
-
131
- rescue ArgumentError => e
132
- logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
133
- end
134
-
135
-
136
- # create_general_class singleclass, behaviour: behaviour, extended_class: extended_class, properties: properties
137
-
138
- # when Hash
139
- # classes.keys.each do |superclass|
140
- # create_general_class superclass, behaviour: "SUPERCLASS", extended_class: nil, properties: nil
141
- # create_general_class classes[superclass], behaviour: "EXTENDEDCLASS", extended_class: superclass, properties: properties
142
- # end
143
- #
144
- # else
145
- # name_class = classes.to_s.capitalize_first_letter
146
- # unless @classes.downcase.include?(name_class.downcase)
147
- #
148
- # if behaviour == "NORMALCLASS"
149
- # command = "CREATE CLASS #{name_class}"
150
- # elsif behaviour == "SUPERCLASS"
151
- # command = "CREATE CLASS #{name_class} ABSTRACT"
152
- # elsif behaviour == "EXTENDEDCLASS"
153
- # name_superclass = extended_class.to_s
154
- # command = "CREATE CLASS #{name_class} EXTENDS #{name_superclass}"
155
- # end
156
- #
157
- # #print "\n #{command} \n"
158
- #
159
- # execute transaction: false do
160
- # [{ type: "cmd",
161
- # language: "sql",
162
- # command: command}]
163
- # end
164
- #
165
- # @classes << name_class
166
- #
167
- # # Add properties
168
- # unless properties.nil?
169
- # create_properties name_class, properties
170
- # end
171
- # end
172
- #
173
- # consts << ActiveOrient::Model.orientdb_class(name: name_class)
174
- # end
175
-
176
- # return consts
177
- #
178
- # rescue RestClient::InternalServerError => e
179
- # logger.progname = 'RestCreate#CreateGeneralClass'
180
- # response = JSON.parse(e.response)['errors'].pop
181
- # logger.error{"#{response['content'].split(':').last }"}
182
- # nil
183
- # end
184
- #end
185
-
186
-
187
- ############## OBJECT #############
188
-
189
-
190
-
191
- =begin
192
- Creates a Record (NOT edge) in the Database and returns this as ActiveOrient::Model-Instance
193
- Creates a Record with the attributes provided in the attributes-hash e.g.
194
- create_record @classname, attributes: {con_id: 343, symbol: 'EWTZ'}
195
-
196
- untested: for hybrid and schema-less documents the following syntax is supported
197
- create_document Account, attributes: {date: 1350426789, amount: 100.34, "@fieldTypes" => "date = t, amount = c"}
198
-
199
- The supported special types are:
200
- 'f' for float
201
- 'c' for decimal
202
- 'l' for long
203
- 'd' for double
204
- 'b' for byte and binary
205
- 'a' for date
206
- 't' for datetime
207
- 's' for short
208
- 'e' for Set, because arrays and List are serialized as arrays like [3,4,5]
209
- 'x' for links
210
- 'n' for linksets
211
- 'z' for linklist
212
- 'm' for linkmap
213
- 'g' for linkbag
214
- =end
215
-
216
- def create_record o_class, attributes: {} # :nodoc: # use Model#create instead
217
- logger.progname = 'RestCreate#CreateRecord'
218
- attributes = yield if attributes.empty? && block_given?
219
- # @class must not quoted! Quote only attributes(strings)
220
- post_argument = {'@class' => classname(o_class)}.merge(attributes.to_orient)
221
- # puts post_argument.inspect
222
- begin
223
- response = @res["/document/#{ActiveOrient.database}"].post post_argument.to_json
224
- data = JSON.parse(response.body)
225
- if o_class.is_a?(Class) && o_class.new.is_a?(ActiveOrient::Model)
226
- o_class.new data
227
- else
228
- ActiveOrient::Model.orientdb_class(name: data['@class'], superclass: :find_ME).new data
229
- end
230
- rescue RestClient::InternalServerError => e
231
- sentence= JSON.parse( e.response)['errors'].last['content']
232
- puts sentence.to_s
233
- if sentence =~ /found duplicated key/
234
- rid = sentence.split("#").last
235
- logger.info{ "found duplicated Key --> loaded #{rid} instead of creating "}
236
- ## reading database content -- maybe update attributes?
237
- get_record rid
238
- else
239
- response = JSON.parse(e.response)['errors'].pop
240
- logger.error{response['content'].split(':')[1..-1].join(':')}
241
- logger.error{"No Object allocated"}
242
- nil # return_value
243
- end
244
- rescue Errno::EADDRNOTAVAIL => e
245
- sleep(2)
246
- retry
247
- end
248
- end
249
- alias create_document create_record
250
-
251
- =begin
252
- Used to create multiple records at once
253
- For example:
254
- $r.create_multiple_records "Month", ["date", "value"], [["June", 6], ["July", 7], ["August", 8]]
255
- It is equivalent to this three functios:
256
- $r.create_record "Month", attributes: {date: "June", value: 6}
257
- $r.create_record "Month", attributes: {date: "July", value: 7}
258
- $r.create_record "Month", attributes: {date: "August", value: 8}
259
-
260
- The function $r.create_multiple_records "Month", ["date", "value"], [["June", 6], ["July", 7], ["August", 8]] will return an array with three element of class "Active::Model::Month".
261
- =end
262
-
263
- def create_multiple_records o_class, values, new_records # :nodoc: # untested
264
- command = "INSERT INTO #{o_class} ("
265
- values.each do |val|
266
- command += "#{val},"
267
- end
268
- command[-1] = ")"
269
- command += " VALUES "
270
- new_records.each do |new_record|
271
- command += "("
272
- new_record.each do |record_value|
273
- case record_value
274
- when String
275
- command += "\'#{record_value}\',"
276
- when Integer
277
- command += "#{record_value},"
278
- when ActiveOrient::Model
279
- command += "##{record_value.rid},"
280
- when Array
281
- if record_value[0].is_a? ActiveOrient::Model
282
- command += "["
283
- record_value.rid.each do |rid|
284
- command += "##{rid},"
285
- end
286
- command[-1] = "]"
287
- command += ","
288
- else
289
- command += "null,"
290
- end
291
- else
292
- command += "null,"
293
- end
294
- end
295
- command[-1] = ")"
296
- command += ","
297
- end
298
- command[-1] = ""
299
- execute transaction: false do # To execute commands
300
- [{ type: "cmd",
301
- language: 'sql',
302
- command: command}]
303
- end
304
- end
305
- # UPDATE <class>|CLUSTER:<cluster>|<recordID>
306
- # [SET|INCREMENT|ADD|REMOVE|PUT <field-name> = <field-value>[,]*]|[CONTENT|MERGE <JSON>]
307
- # [UPSERT]
308
- # [RETURN <returning> [<returning-expression>]]
309
- # [WHERE <conditions>]
310
- # [LOCK default|record]
311
- # [LIMIT <max-records>] [TIMEOUT <timeout>]
312
-
313
- =begin
314
- update or insert one record is implemented as upsert.
315
- The where-condition is merged into the set-attributes if its a hash.
316
- Otherwise it's taken unmodified.
317
-
318
- The method returns the included or the updated dataset
319
-
320
- ## to do
321
- # yield works for updated and for inserted datasets
322
- # upsert ( ) do | what, record |
323
- # if what == :insert
324
- # do stuff with insert
325
- # if what == :update
326
- # do stuff with update
327
- # end
328
- # returns nil if no insert and no update was made, ie. the dataset is identical to the given attributes
329
- =end
330
- def upsert o_class, set: {}, where: {} # :nodoc: use Model#Upsert instead
331
- logger.progname = 'RestCreate#Upsert'
332
- if where.blank?
333
- new_record = create_record(o_class, attributes: set)
334
- yield new_record if block_given? # in case if insert execute optional block
335
- new_record # return_value
336
- else
337
- specify_return_value = block_given? ? "" : "return after @this"
338
- set.merge! where if where.is_a?( Hash ) # copy where attributes to set
339
- command = "Update #{classname(o_class)} set #{generate_sql_list( set ){','}} upsert #{specify_return_value} #{compose_where where}"
340
- # puts "COMMAND: #{command} "
341
- result = execute tolerated_error_code: /found duplicated key/, raw: true do # To execute commands
342
- [ { type: "cmd", language: 'sql', command: command}]
343
- end
344
- result =result.pop if result.is_a? Array
345
- if result.is_a? Hash
346
- if result.has_key?('@class')
347
- if o_class.is_a?(Class) && o_class.new.is_a?(ActiveOrient::Model)
348
- o_class.new result
349
- else
350
- AddctiveOrient::Model.orientdb_class(name: data['@class'], superclass: :find_ME).new data
351
- end
352
- elsif result.has_key?('value')
353
- the_record= get_records(from: o_class, where: where, limit: 1).pop
354
- ## process Code if a new dataset is inserted
355
- if result['value'].to_i == 1
356
- yield the_record if block_given?
357
- logger.info{ "Dataset updated" }
358
- elsif result['value'].to_i == 0
359
- logger.info{ "Dataset inserted"}
360
- end
361
- the_record # return_value
362
-
363
- else
364
- logger.error{ "Unexpected result form Query \n #{command} \n Result: #{result}" }
365
- raise ArgumentError
366
- end
367
- else
368
- logger.debug{ "No Insert or Update nessesary \n #{command} " }
369
- end
370
- end
371
- end
372
- ############### PROPERTIES #############
373
-
374
- =begin
375
- Creates properties and optional an associated index as defined in the provided block
376
- create_properties(classname or class, properties as hash){index}
377
-
378
- The default-case
379
- create_properties(:my_high_sophisticated_database_class,
380
- con_id: {type: :integer},
381
- details: {type: :link, linked_class: 'Contracts'}) do
382
- contract_idx: :notunique
383
- end
384
-
385
- A composite index
386
- create_properties(:my_high_sophisticated_database_class,
387
- con_id: {type: :integer},
388
- symbol: {type: :string}) do
389
- {name: 'indexname',
390
- on: [:con_id, :details] # default: all specified properties
391
- type: :notunique # default: :unique
392
- }
393
- end
394
- =end
395
-
396
- def create_properties o_class, all_properties, &b
397
- logger.progname = 'RestCreate#CreateProperties'
398
- all_properties_in_a_hash = HashWithIndifferentAccess.new
399
- all_properties.each{|field, args| all_properties_in_a_hash.merge! translate_property_hash(field, args)}
400
- count=0
401
- begin
402
- if all_properties_in_a_hash.is_a?(Hash)
403
- response = @res["/property/#{ActiveOrient.database}/#{classname(o_class)}"].post all_properties_in_a_hash.to_json
404
- # response.body.to_i returns response.code, only to_f.to_i returns the correrect value
405
- count= response.body.to_f.to_i if response.code == 201
406
- end
407
- rescue RestClient::InternalServerError => e
408
- logger.progname = 'RestCreate#CreateProperties'
409
- response = JSON.parse(e.response)['errors'].pop
410
- error_message = response['content'].split(':').last
411
- logger.error{"Properties in #{classname(o_class)} were NOT created"}
412
- logger.error{"The Error was: #{response['content'].split(':').last}"}
413
- nil
414
- end
415
- ### index
416
- if block_given?# && count == all_properties_in_a_hash.size
417
- index = yield
418
- if index.is_a?(Hash)
419
- # puts "index_class: #{o_class}"
420
- # puts "index: "+index.inspect
421
- if index.size == 1
422
- create_index o_class, name: index.keys.first, on: all_properties_in_a_hash.keys, type: index.values.first
423
- else
424
- index_hash = HashWithIndifferentAccess.new(type: :unique, on: all_properties_in_a_hash.keys).merge index
425
- create_index o_class, name: index_hash[:name], on: index_hash[:on], type: index_hash[:type]
426
- end
427
- end
428
- end
429
- count # return_value
430
- end
431
-
432
- =begin
433
- Create a single property on class-level.
434
- Supported types: https://orientdb.com/docs/last/SQL-Create-Property.html
435
- If index is to be specified, it's defined in the optional block
436
- create_property(class, field){:unique | :notunique} --> creates an automatic-Index on the given field
437
- create_property(class, field){{»name« => :unique | :notunique | :full_text}} --> creates a manual index
438
- =end
439
-
440
- def create_property o_class, field, index: nil, **args, &b
441
- logger.progname = 'RestCreate#CreateProperty'
442
- args= { type: :integer} if args.blank? # the default case
443
- c = create_properties o_class, {field => args}
444
- if index.nil? && block_given?
445
- index = yield
446
- end
447
- if index.present?
448
- if index.is_a?(String) || index.is_a?(Symbol)
449
- create_index o_class, name: field, type: index
450
- elsif index.is_a? Hash
451
- bez = index.keys.first
452
- create_index o_class, name: bez, type: index[bez], on: [field]
453
- end
454
- end
455
- end
456
-
457
- ################# INDEX ###################
458
-
459
- # Used to create an index
460
-
461
- def create_index o_class, name:, on: :automatic, type: :unique
462
- logger.progname = 'RestCreate#CreateIndex'
463
- begin
464
- c = classname o_class
465
- # puts "CREATE INDEX: class: #{c.inspect}"
466
- execute transaction: false do
467
- command = if on == :automatic
468
- "CREATE INDEX #{c}.#{name} #{type.to_s.upcase}"
469
- elsif on.is_a? Array
470
- "CREATE INDEX #{name} ON #{c}(#{on.join(', ')}) #{type.to_s.upcase}"
471
- else
472
- "CREATE INDEX #{name} ON #{c}(#{on.to_s}) #{type.to_s.upcase}"
473
- #nil
474
- end
475
- #puts "command: #{command}"
476
- {type: "cmd", language: 'sql', command: command} if command.present?
477
- end
478
- logger.info{"Index on #{c} based on #{name} created."}
479
- rescue RestClient::InternalServerError => e
480
- response = JSON.parse(e.response)['errors'].pop
481
- error_message = response['content'].split(':').last
482
- logger.error{"Index not created."}
483
- logger.error{"Error-code #{response['code']} --> #{response['content'].split(':').last }"}
484
- nil
485
- end
486
- end
487
-
488
- end