active-orient 0.6 → 0.42

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