arcadedb 0.3.1 → 0.4

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.
@@ -0,0 +1,87 @@
1
+ module Arcade
2
+ module Support
3
+ module Model
4
+
5
+ def resolve_edge_name *edge_names
6
+ edge_names.map do | edge_name |
7
+ case edge_name
8
+ when nil
9
+ ""
10
+ when Class
11
+ "'" + edge_name.database_name + "'"
12
+ when String
13
+ "'" + edge_name + "'"
14
+ end
15
+ end.join(',')
16
+ end
17
+
18
+
19
+ # used by array#allocate_model
20
+ def _allocate_model response=nil, auto = Config.autoload
21
+
22
+
23
+ if response.is_a? Hash
24
+ # save rid to a safe place
25
+ temp_rid = response.delete :"@rid"
26
+ type = response.delete :"@type"
27
+ cat = response.delete :"@cat"
28
+
29
+ return response if type.nil?
30
+ temp_rid = "#0:0" if temp_rid.nil?
31
+ type = "d" if type.nil?
32
+ # extract type infos and convert to database-name
33
+ n, type_name = type.camelcase_and_namespace
34
+ n = self.namespace if n.nil?
35
+ # autoconvert rid's in attributes to model-records (exclude edges!)
36
+ if auto && !(cat.to_s =='e')
37
+ response.transform_values! do |x|
38
+ case x
39
+ when String
40
+ x.rid? ? x.load_rid : x
41
+ when Array
42
+ x.map do| y |
43
+ if y.is_a?(Hash) && y.include?(:@type) # if embedded documents are present, load them
44
+ y.allocate_model(false)
45
+ elsif y.rid? # if links are present, load the object
46
+ y.load_rid(false) # do not autoload further records, prevents from recursive locking
47
+ else
48
+ y
49
+ end
50
+ end
51
+ when Hash
52
+ if x.include?(:@type)
53
+ x.allocate_model(false)
54
+ else
55
+ x.transform_values!{|z| z.rid? ? z.load_rid(false) : z }
56
+ end
57
+ else
58
+ x
59
+ end
60
+ end
61
+ end
62
+ # choose the appropriate class
63
+ klass= Dry::Core::ClassBuilder.new( name: type_name, parent: nil, namespace: n).call
64
+ #
65
+ begin
66
+ # create a new object of that class with the appropriate attributes
67
+ new = klass.new **response.merge( rid: temp_rid )
68
+ rescue ::ArgumentError => e
69
+ raise "Allocation of class #{klass.to_s} failed"
70
+ end
71
+ # map additional attributes to `input`
72
+ v = response.except *new.attributes.keys
73
+ v.empty? ? new : new.new( values: v.except( :"@in", :"@out" ) )
74
+ elsif response.is_a? Array
75
+ puts "Allocate_model..detected array"
76
+ ## recursive behavior, just in case
77
+ response.map{ | y | _allocate_model y }
78
+ elsif response.rid?
79
+ # Autoload rid's
80
+ response.load_rid
81
+ else
82
+ response
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,20 @@
1
+ module Arcade
2
+ module Support
3
+ module Object
4
+ # this is the rails method
5
+ def present?
6
+ !blank?
7
+ end
8
+
9
+ # File activesupport/lib/active_support/core_ext/object/blank.rb, line 46
10
+ def presence
11
+ self if present?
12
+ end
13
+ # File activesupport/lib/active_support/core_ext/object/blank.rb, line 19
14
+ def blank?
15
+ respond_to?(:empty?) ? !!empty? : !self
16
+ end
17
+ end
18
+ end
19
+ end
20
+ Object.include Arcade::Support::Object
@@ -0,0 +1,74 @@
1
+ #require 'active_support/inflector'
2
+
3
+ module Arcade
4
+ module Support
5
+ module Sql
6
+
7
+ =begin
8
+ supports
9
+ where: 'string'
10
+ where: { property: 'value', property: value, ... }
11
+ where: ['string, { property: value, ... }, ... ]
12
+
13
+ Used by update and select
14
+
15
+ _Usecase:_
16
+ compose_where 'z=34', u: 6
17
+ => "where z=34 and u = 6"
18
+ =end
19
+
20
+ def compose_where *arg , &b
21
+ arg = arg.flatten.compact
22
+
23
+ unless arg.blank?
24
+ g= generate_sql_list( arg , &b)
25
+ "where #{g}" unless g.empty?
26
+ end
27
+ end
28
+
29
+ =begin
30
+ designs a list of "Key = Value" pairs combined by "and" or the binding provided by the block
31
+ ORD.generate_sql_list where: 25 , upper: '65'
32
+ => "where=25 and upper='65'"
33
+ ORD.generate_sql_list( con_id: 25 , symbol: :G) { ',' }
34
+ => "con_id=25 , symbol='G'"
35
+
36
+ If »NULL« should be addressed, { key: nil } is translated to "key = NULL" (used by set: in update and upsert),
37
+ { key: [nil] } is translated to "key is NULL" ( used by where )
38
+
39
+ =end
40
+ def generate_sql_list attributes = {}, &b
41
+ fill = block_given? ? yield : 'and'
42
+ case attributes
43
+ when ::Hash
44
+ attributes.map do |key, value|
45
+ case value
46
+ when nil
47
+ "#{key}=NULL"
48
+ when ::Array
49
+ if value == [nil]
50
+ "#{key} is NULL"
51
+ else
52
+ "#{key} in #{value.to_db}"
53
+ end
54
+ when Range
55
+ "#{key} between #{value.first.to_or} and #{value.last.to_or} "
56
+ else # String, Symbol, Time, Trueclass, Falseclass ...
57
+ "#{key}=#{value.to_or}"
58
+ end
59
+ end.join(" #{fill} ")
60
+ when ::Array
61
+ attributes.map{|y| generate_sql_list y, &b }.join( " #{fill} " )
62
+ when String
63
+ attributes
64
+ when Symbol, Numeric
65
+ attributes.to_s
66
+ end
67
+ end
68
+
69
+
70
+ # used both in Query and MatchConnect
71
+ # while and where depend on @q, a struct
72
+ end # module
73
+ end # module
74
+ end # modul
@@ -0,0 +1,116 @@
1
+ module Arcade
2
+ module Support
3
+ module String
4
+ #modified version of
5
+ # https://stackoverflow.com/questions/63769351/convert-string-to-camel-case-in-ruby
6
+ # returns an Array [ Namespace(first character upcase) , Type(class, camelcase) ]
7
+ #
8
+ # if the namespace is not found, joins all string-parts
9
+ def camelcase_and_namespace
10
+ if self.count("_") >= 1 || self.count('-') >=1
11
+ delimiters = Regexp.union(['-', '_'])
12
+ n,c= self.split(delimiters).then { |first, *rest| [first.tap {|s| s[0] = s[0].upcase}, rest.map(&:capitalize).join] }
13
+ ## if base is the first part of the type-name, probably Arcade::Base is choosen a namespace. thats wrong
14
+ namespace_present = unless n == 'Base'
15
+ Object.const_get(n) rescue false # Database.namespace
16
+ else
17
+ false
18
+ end
19
+ # if no namespace is found, leave it empty and return the capitalized string as class name
20
+ namespace_present && !c.nil? ? [namespace_present,c] : [Database.namespace, n+c]
21
+ else
22
+ [ Database.namespace, self.capitalize ]
23
+ end
24
+ end
25
+
26
+ def snake_case
27
+ n= if split('::').first == Database.namespace.to_s
28
+ split('::')[1..-1].join
29
+ else
30
+ split("::").join
31
+ end
32
+ n.gsub(/([^\^])([A-Z])/,'\1_\2').downcase
33
+ end
34
+
35
+ # borrowed from ActiveSupport::Inflector
36
+ def underscore
37
+ word = self.dup
38
+ word.gsub!(/::/, '/')
39
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
40
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
41
+ word.tr!("-", "_")
42
+ word.downcase!
43
+ word
44
+ end
45
+ def capitalize_first_letter
46
+ self.sub(/^(.)/) { $1.capitalize }
47
+ end
48
+ # a rid is either #nn:nn or nn:nn
49
+ def rid?
50
+ self =~ /\A[#]{,1}[0-9]{1,}:[0-9]{1,}\z/
51
+ end
52
+ # return a valid rid (format: "nn:mm") or nil
53
+ def rid
54
+ self["#"].nil? ? "#"+ self : self if rid?
55
+ end
56
+
57
+ def where **args
58
+ if rid?
59
+ from_db.where **args
60
+ end
61
+ end
62
+ def to_a
63
+ [ self ]
64
+ end
65
+
66
+ def quote
67
+ str = self.dup
68
+ if str[0, 1] == "'" && str[-1, 1] == "'"
69
+ self
70
+ else
71
+ last_pos = 0
72
+ while (pos = str.index("'", last_pos))
73
+ str.insert(pos, "\\") if pos > 0 && str[pos - 1, 1] != "\\"
74
+ last_pos = pos + 1
75
+ end
76
+ "'#{str}'"
77
+ end
78
+ end
79
+
80
+ ## Load the database object if the string is a rid
81
+ # (Default: No Autoloading of rid-links)
82
+ def load_rid autocomplete = false
83
+ db.get( self ){ autocomplete } if rid? rescue nil
84
+ end
85
+
86
+ # updates the record ### retired in favour of Arcade::Base.update
87
+ # def update **args
88
+ ## remove empty Arrays and Hashes.
89
+ ## To remove attributes, use the remove syntax, do not privide empty fields to update!
90
+ # args.delete_if{|_,y|( y.is_a?(Array) || y.is_a?(Hash)) && y.blank? }
91
+ # return nil if args.empty?
92
+ # Arcade::Query.new( from: self , kind: :update, set: args).execute
93
+ # end
94
+
95
+ def to_human
96
+ self
97
+ end
98
+ private
99
+ def db
100
+ Arcade::Init.db
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ String.include Arcade::Support::String
107
+
108
+ module Types
109
+ include Dry.Types()
110
+
111
+ # include in attribute definitions
112
+ Rid = String.constrained( format: /\A[#]{1}[0-9]{1,}:[0-9]{1,}\z/ )
113
+ Blockchain = String.constrained( format: /^(algo|eth|btc)$/ ) # add other blockchain symbols here
114
+ Email = String.constrained( format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i )
115
+
116
+ end
data/rails/arcade.rb ADDED
@@ -0,0 +1,20 @@
1
+
2
+ ## This is an init-script intended to be copied to
3
+ ## rails-root/config/initializers
4
+
5
+ module Arcade
6
+ ProjectRoot = Rails.root
7
+ puts "Root: #{Rails.root}"
8
+ puts "Alternative: #{File.expand_path("../",__FILE__)}"
9
+ end
10
+ ## Integrate a namespaced model
11
+ #module HC
12
+ #
13
+ #end
14
+
15
+
16
+
17
+
18
+
19
+
20
+
data/rails/config.yml ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ :active_orient:
3
+ ## Namespace: Prefix of Model-Objects. :self -> ActiveOrient::Model::{name}
4
+ ## :object => No Prefix
5
+ ## :active_orient => ActiveOrient::{name}
6
+ :namespace: :object
7
+ ## model_dir: Path to model-files relative to the root of the application
8
+ ## ie. app/model or model
9
+ :model_dir: 'lib/orient'
10
+
data/rails/connect.yml ADDED
@@ -0,0 +1,17 @@
1
+ ---
2
+ :orientdb:
3
+ :server: localhost # 172.28.50.109
4
+ :port: 2480
5
+ :logger: stdout # 'file' or 'stdout'
6
+ :database:
7
+ :development: GratefulDeadConcerts
8
+ :production: hcn_data
9
+ :test: temp
10
+ :admin:
11
+ :user: root
12
+ :pass: root
13
+ :auth:
14
+ :user: root
15
+ :pass: root
16
+
17
+ # hfx: 101
data/rails.md ADDED
@@ -0,0 +1,147 @@
1
+ # ArcadeDB and Rails
2
+
3
+ The usage of ArcadeDB in Rails requires just a few steps.
4
+ Based on a Rails 7 installation
5
+
6
+ ```ruby
7
+ rvm install 3.1
8
+ rvm use 3.1
9
+ gem install bundler
10
+ gem install rails
11
+ rails -v # Rails 7.xx
12
+ ```
13
+
14
+ Create your working directory and initialize the system
15
+
16
+ ```ruby
17
+ mkdir rails_project; cd rails_project
18
+ rails new -OCT -css {tailwind, sass, bulma etc} .
19
+ ```
20
+ This initializes a Rails-Stack, without active-record, action-cable and the test-suite.
21
+ (We will use rspec later)
22
+
23
+ This can be checked by inspecting «/config/application.rb «
24
+
25
+ ```ruby
26
+ ./bin/dev
27
+ ```
28
+ should work at this stage.
29
+
30
+ ## Modify the Gemfile
31
+ Inform rails to use arcadedb
32
+
33
+ ```
34
+ echo " gem 'arcadedb' , :path => '/home/your_cloned_active_orient_path/activeorient' " >> Gemfile
35
+ # or
36
+
37
+ echo " gem 'arcadedb' , :git => 'https://github.com/topofocus/arcadedb.git' " >> Gemfile
38
+
39
+ ```
40
+
41
+ Run the bundler
42
+
43
+ ```
44
+ bundle install & bundle update
45
+ ```
46
+ ## Copy Initializer and Configuration Files
47
+ change to the base-dir of the gem
48
+ --> bundle show active-orient
49
+ then copy
50
+
51
+ * rails/arcade.rb to config/initializers in the rails-project dir
52
+ * rails/.arcade.yml to config/ in the rails project
53
+
54
+ and modify the arcade.yml-file accordingly.
55
+
56
+
57
+ The database is present in the rails console, and
58
+ ```ruby
59
+ rails c
60
+ puts DB.types
61
+
62
+
63
+ ```
64
+ should display details.
65
+
66
+
67
+ **Notice** The spring-facility is running in the background. Stop the server prior reloading
68
+ the console ( ./bin/spring stop ).
69
+
70
+ ## Model-files
71
+ The final step is to generate Model-Files.
72
+
73
+ In «/config/config.yml» the «:model_dir»-var points to
74
+ the location of the model-files. The default is 'lib/orient'. Change to your needs.
75
+ Don't use the app directory, as its autoloaded too early.
76
+
77
+ Upon startup, present model-classes are destroyed and overridden by present files in the autoload directory.
78
+
79
+ After envoking the rails console, the logfile displays sucessfully loaded and missing files, ie.
80
+
81
+ ```
82
+ 14.01.(08:28:45) INFO->ModelClass#RequireModelFile:..:model-file not present: /home/topo/workspace/orient-rails/lib/orient/followed_by.rb
83
+ 14.01.(08:28:45) INFO->ModelClass#RequireModelFile:..:/home/topo/workspace/orient-rails/lib/orient/v.rb sucessfully loaded
84
+ ```
85
+
86
+ ## Model-file Example
87
+
88
+ To query the GratefulDeadConcerts Database, «v.rb» hosts the essential model methods.
89
+ As always, use «def self.{method}« for class methods and simply «def {method}» for methods working on the record level.
90
+
91
+ ```
92
+ 1 class V
93
+ 2 def self.artists **attributes
94
+ 3 names 'artist', **attributes
95
+ 4 end
96
+ 5
97
+ 6 def self.songs **attributes
98
+ 7 names 'song', **attributes
99
+ 8 end
100
+ 9
101
+ 10 def self.types
102
+ 11 oo = OrientSupport::OrientQuery
103
+ 12 this_query = oo.new distinct: [:type, :a ] # --> "select distinct( type ) as a "
104
+ 13 query_database( this_query ).a # returns an array of types, i.e. ["artist", "song"]
105
+ 14 end
106
+ 15 private
107
+ 16 def self.names type, sort: :asc, limit: 20, skip: 0
108
+ 17 puts "in names"
109
+ 18 oo = OrientSupport::OrientQuery
110
+ 19 query_database oo.new( where: {type: type },
111
+ 20 order: { name: sort } ,
112
+ 21 limit: limit ,
113
+ 22 skip: skip )
114
+ 23 end
115
+ 24 end
116
+
117
+ ```
118
+
119
+ Now
120
+
121
+ ```ruby
122
+ V.types
123
+ V.artists limit: 15, skip: 34, sort: :desc
124
+ ```
125
+ queries the database, fetches 15 artists.
126
+
127
+ ## Routing
128
+
129
+ for now, restful routing has some restrictions.
130
+
131
+ Rails-routing is depending on the "id"-attribute. Even if this is remapped to rid, the ressources-entries in "config/routes.rb" have to be modified by
132
+
133
+ ```ruiby
134
+ resources :{controller}, id: /[^\/]+/
135
+ ```
136
+ this enables the usage of id: "xx:yy"
137
+
138
+ In the controller the record is fetched as usual:
139
+ ```ruby
140
+ def show
141
+ @{your coice} = {ActiveOrient-Model-Class}.autoload_object params[:id]
142
+ end
143
+ ```
144
+
145
+
146
+
147
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arcadedb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hartmut Bischoff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-16 00:00:00.000000000 Z
11
+ date: 2023-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: typhoeus
56
+ name: httpx
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -108,12 +108,71 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: dry-configurable
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Provides access to ArcadeDB from ruby
112
126
  email: topofocus@gmail.com
113
127
  executables: []
114
128
  extensions: []
115
129
  extra_rdoc_files: []
116
- files: []
130
+ files:
131
+ - ".gitignore"
132
+ - CHANGELOG.md
133
+ - Gemfile
134
+ - Gemfile.lock
135
+ - Guardfile
136
+ - LICENSE
137
+ - README.md
138
+ - Rakefile
139
+ - arcade.yml
140
+ - arcadedb.gemspec
141
+ - bin/+
142
+ - bin/console
143
+ - examples/books.rb
144
+ - examples/relation_1__1.rb
145
+ - examples/relation_1__n.rb
146
+ - examples/relation_n_n.rb
147
+ - lib/arcade.rb
148
+ - lib/arcade/api/operations.rb
149
+ - lib/arcade/api/primitives.rb
150
+ - lib/arcade/base.rb
151
+ - lib/arcade/database.rb
152
+ - lib/arcade/errors.rb
153
+ - lib/arcade/logging.rb
154
+ - lib/arcade/version.rb
155
+ - lib/config.rb
156
+ - lib/init.rb
157
+ - lib/match.rb
158
+ - lib/model/basicdocument.rb
159
+ - lib/model/basicedge.rb
160
+ - lib/model/basicvertex.rb
161
+ - lib/model/document.rb
162
+ - lib/model/edge.rb
163
+ - lib/model/vertex.rb
164
+ - lib/models.rb
165
+ - lib/query.rb
166
+ - lib/support/class.rb
167
+ - lib/support/conversions.rb
168
+ - lib/support/model.rb
169
+ - lib/support/object.rb
170
+ - lib/support/sql.rb
171
+ - lib/support/string.rb
172
+ - rails.md
173
+ - rails/arcade.rb
174
+ - rails/config.yml
175
+ - rails/connect.yml
117
176
  homepage: https://github.com/topofocus/arcadedb
118
177
  licenses:
119
178
  - MIT
@@ -133,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
192
  - !ruby/object:Gem::Version
134
193
  version: '0'
135
194
  requirements: []
136
- rubygems_version: 3.3.7
195
+ rubygems_version: 3.4.6
137
196
  signing_key:
138
197
  specification_version: 4
139
198
  summary: Ruby Interface to ArcadeDB