arcadedb 0.3.1 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +57 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +25 -0
- data/Gemfile.lock +186 -0
- data/Guardfile +30 -0
- data/LICENSE +21 -0
- data/README.md +242 -0
- data/Rakefile +11 -0
- data/arcade.yml +23 -0
- data/arcadedb.gemspec +32 -0
- data/bin/+ +106 -0
- data/bin/console +126 -0
- data/examples/books.rb +139 -0
- data/examples/relation_1__1.rb +149 -0
- data/examples/relation_1__n.rb +56 -0
- data/examples/relation_n_n.rb +194 -0
- data/lib/arcade/api/operations.rb +257 -0
- data/lib/arcade/api/primitives.rb +98 -0
- data/lib/arcade/base.rb +454 -0
- data/lib/arcade/database.rb +367 -0
- data/lib/arcade/errors.rb +71 -0
- data/lib/arcade/logging.rb +38 -0
- data/lib/arcade/version.rb +3 -0
- data/lib/arcade.rb +36 -0
- data/lib/config.rb +72 -0
- data/lib/init.rb +50 -0
- data/lib/match.rb +216 -0
- data/lib/model/basicdocument.rb +7 -0
- data/lib/model/basicedge.rb +6 -0
- data/lib/model/basicvertex.rb +6 -0
- data/lib/model/document.rb +10 -0
- data/lib/model/edge.rb +47 -0
- data/lib/model/vertex.rb +238 -0
- data/lib/models.rb +6 -0
- data/lib/query.rb +384 -0
- data/lib/support/class.rb +13 -0
- data/lib/support/conversions.rb +295 -0
- data/lib/support/model.rb +87 -0
- data/lib/support/object.rb +20 -0
- data/lib/support/sql.rb +74 -0
- data/lib/support/string.rb +116 -0
- data/rails/arcade.rb +20 -0
- data/rails/config.yml +10 -0
- data/rails/connect.yml +17 -0
- data/rails.md +147 -0
- metadata +64 -5
data/lib/query.rb
ADDED
@@ -0,0 +1,384 @@
|
|
1
|
+
#require ' active_support/inflector'
|
2
|
+
|
3
|
+
module Arcade
|
4
|
+
|
5
|
+
######################## Query ###################################
|
6
|
+
|
7
|
+
QueryAttributes = Struct.new( :kind, :projection, :where, :let, :order, :while, :misc,
|
8
|
+
:class, :return, :aliases, :database,
|
9
|
+
:set, :remove, :group, :skip, :limit, :unwind, :map )
|
10
|
+
|
11
|
+
class Query
|
12
|
+
include Support::Sql
|
13
|
+
include Support::Model
|
14
|
+
|
15
|
+
|
16
|
+
#
|
17
|
+
def initialize **args
|
18
|
+
@q = QueryAttributes.new args[:kind] || 'select' ,
|
19
|
+
[], # :projection
|
20
|
+
[], # :where ,
|
21
|
+
[], # :let ,
|
22
|
+
[], # :order,
|
23
|
+
[], # :while,
|
24
|
+
[] , # misc
|
25
|
+
'', # class
|
26
|
+
'', # return
|
27
|
+
[], # aliases
|
28
|
+
'', # database
|
29
|
+
[], #set,
|
30
|
+
[] # remove
|
31
|
+
args.each{|k,v| send k, v}
|
32
|
+
@fill = block_given? ? yield : 'and'
|
33
|
+
end
|
34
|
+
|
35
|
+
=begin
|
36
|
+
where: "r > 9" --> where r > 9
|
37
|
+
where: {a: 9, b: 's'} --> where a = 9 and b = 's'
|
38
|
+
where:[{ a: 2} , 'b > 3',{ c: 'ufz' }] --> where a = 2 and b > 3 and c = 'ufz'
|
39
|
+
=end
|
40
|
+
def method_missing method, *arg, &b # :nodoc:
|
41
|
+
if method ==:while || method=='while'
|
42
|
+
while_s arg.first
|
43
|
+
else
|
44
|
+
@q[:misc] << method.to_s << generate_sql_list(arg)
|
45
|
+
end
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def misc # :nodoc:
|
50
|
+
@q[:misc].join(' ') unless @q[:misc].empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def subquery # :nodoc:
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def kind value=nil
|
58
|
+
if value.present?
|
59
|
+
@q[:kind] = value
|
60
|
+
self
|
61
|
+
else
|
62
|
+
@q[:kind]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
=begin
|
66
|
+
Output the compiled query
|
67
|
+
Parameter: destination (rest, batch )
|
68
|
+
If the query is submitted via the REST-Interface (as get-command), the limit parameter is extracted.
|
69
|
+
=end
|
70
|
+
|
71
|
+
def compose(destination: :batch)
|
72
|
+
if kind.to_sym == :update
|
73
|
+
return_statement = "return after " + ( @q[:aliases].empty? ? "$current" : @q[:aliases].first.to_s)
|
74
|
+
[ 'update', target, set, remove, return_statement, where ].compact.join(' ')
|
75
|
+
elsif kind.to_sym == :"update_map"
|
76
|
+
[ "update", target, map, where, misc ].compact.join(' ')
|
77
|
+
elsif kind.to_sym == :update!
|
78
|
+
[ 'update', target, set, where, misc ].compact.join(' ')
|
79
|
+
# elsif kind.to_sym == :create # relict of orientdb
|
80
|
+
# [ "CREATE VERTEX", target, set ].compact.join(' ')
|
81
|
+
# [ kind, target, set, return_statement ,where, limit, misc ].compact.join(' ')
|
82
|
+
elsif kind.to_sym == :upsert
|
83
|
+
set( generate_sql_list( @q[:where] ){ @fill || 'and' } ) if set.nil?
|
84
|
+
return_statement = "return after " + ( @q[:aliases].empty? ? "$current" : @q[:aliases].first.to_s)
|
85
|
+
[ "update", target, set,"upsert", return_statement, where, limit, misc ].compact.join(' ')
|
86
|
+
#[ kind, where, return_statement ].compact.join(' ')
|
87
|
+
elsif destination == :rest
|
88
|
+
[ kind, projection, from, let, where, subquery, misc, order, group_by, unwind, skip].compact.join(' ')
|
89
|
+
else
|
90
|
+
[ kind, projection, from, let, where, subquery, while_s, misc, order, group_by, limit, unwind, skip].compact.join(' ')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
alias :to_s :compose
|
94
|
+
|
95
|
+
|
96
|
+
def to_or
|
97
|
+
compose.to_or
|
98
|
+
end
|
99
|
+
|
100
|
+
def target arg = nil
|
101
|
+
if arg.present?
|
102
|
+
@q[:database] = arg
|
103
|
+
self # return query-object
|
104
|
+
elsif @q[:database].present?
|
105
|
+
the_argument = @q[:database]
|
106
|
+
case @q[:database]
|
107
|
+
when Base # a single record
|
108
|
+
the_argument.rid
|
109
|
+
when self.class # result of a query
|
110
|
+
' ( '+ the_argument.compose + ' ) '
|
111
|
+
when Class
|
112
|
+
the_argument.database_name
|
113
|
+
else
|
114
|
+
if the_argument.to_s.rid? # a string with "#ab:cd"
|
115
|
+
the_argument
|
116
|
+
else # a database-class-name
|
117
|
+
the_argument.to_s
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
raise "cannot complete until a target is specified"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
=begin
|
126
|
+
from can either be a Databaseclass to operate on or a Subquery providing data to query further
|
127
|
+
=end
|
128
|
+
def from arg = nil
|
129
|
+
if arg.present?
|
130
|
+
@q[:database] = arg
|
131
|
+
self # return query-object
|
132
|
+
elsif @q[:database].present? # read from
|
133
|
+
"from #{ target }"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def order value = nil
|
139
|
+
if value.present?
|
140
|
+
@q[:order] << value
|
141
|
+
self
|
142
|
+
elsif @q[:order].present?
|
143
|
+
|
144
|
+
"order by " << @q[:order].compact.flatten.map do |o|
|
145
|
+
case o
|
146
|
+
when String, Symbol, Array
|
147
|
+
o.to_s
|
148
|
+
else
|
149
|
+
o.map{|x,y| "#{x} #{y}"}.join(" ")
|
150
|
+
end # case
|
151
|
+
end.join(', ')
|
152
|
+
else
|
153
|
+
''
|
154
|
+
end # unless
|
155
|
+
end # def
|
156
|
+
|
157
|
+
|
158
|
+
def database_class # :nodoc:
|
159
|
+
@q[:database]
|
160
|
+
end
|
161
|
+
|
162
|
+
def database_class= arg # :nodoc:
|
163
|
+
@q[:database] = arg
|
164
|
+
end
|
165
|
+
|
166
|
+
def distinct d
|
167
|
+
@q[:projection] << "distinct " + generate_sql_list( d ){ ' as ' }
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
class << self
|
172
|
+
def mk_simple_setter *m
|
173
|
+
m.each do |def_m|
|
174
|
+
define_method( def_m ) do | value=nil |
|
175
|
+
if value.present?
|
176
|
+
@q[def_m] = value
|
177
|
+
self
|
178
|
+
elsif @q[def_m].present?
|
179
|
+
"#{def_m.to_s} #{generate_sql_list(@q[def_m]){' ,'}}"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
def mk_std_setter *m
|
185
|
+
m.each do |def_m|
|
186
|
+
define_method( def_m ) do | value = nil |
|
187
|
+
if value.present?
|
188
|
+
@q[def_m] << case value
|
189
|
+
when String
|
190
|
+
value
|
191
|
+
when ::Hash
|
192
|
+
value.map{|k,v| "#{k} = #{v.to_or}"}.join(", ")
|
193
|
+
else
|
194
|
+
raise "Only String or Hash allowed in #{def_m} statement"
|
195
|
+
end
|
196
|
+
self
|
197
|
+
elsif @q[def_m].present?
|
198
|
+
"#{def_m.to_s} #{@q[def_m].join(',')}"
|
199
|
+
end # branch
|
200
|
+
end # def_method
|
201
|
+
end # each
|
202
|
+
end # def
|
203
|
+
end # class << self
|
204
|
+
mk_simple_setter :limit, :skip, :unwind
|
205
|
+
mk_std_setter :set, :remove
|
206
|
+
|
207
|
+
def while_s value=nil # :nodoc:
|
208
|
+
if value.present?
|
209
|
+
@q[:while] << value
|
210
|
+
self
|
211
|
+
elsif @q[:while].present?
|
212
|
+
"while #{ generate_sql_list( @q[:while] ) }"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
def where value=nil # :nodoc:
|
216
|
+
if value.present?
|
217
|
+
if value.is_a?( Hash ) && value.size >1
|
218
|
+
value.each {| a, b | where( {a => b} ) }
|
219
|
+
else
|
220
|
+
@q[:where] << value
|
221
|
+
end
|
222
|
+
self
|
223
|
+
elsif @q[:where].present?
|
224
|
+
"where #{ generate_sql_list( @q[:where] ){ @fill || 'and' } }"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def as a=nil
|
229
|
+
if a
|
230
|
+
@q[:as] = a # subsequent calls overwrite previous entries
|
231
|
+
else
|
232
|
+
if @q[:as].blank?
|
233
|
+
nil
|
234
|
+
else
|
235
|
+
"as: #{ @q[:as] }"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# update_map - update an embedded map
|
241
|
+
def map value=nil
|
242
|
+
if value.present?
|
243
|
+
@q[:map] = value
|
244
|
+
self
|
245
|
+
elsif @q[:map].present?
|
246
|
+
# only one pair is supported
|
247
|
+
"set #{@q[:map].keys.first} = #{@q[:map].values.first.to_or}"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
def let value = nil
|
251
|
+
if value.present?
|
252
|
+
@q[:let] << value
|
253
|
+
self
|
254
|
+
elsif @q[:let].present?
|
255
|
+
"let " << @q[:let].map do |s|
|
256
|
+
case s
|
257
|
+
when String
|
258
|
+
s
|
259
|
+
when ::Hash
|
260
|
+
s.map do |x,y|
|
261
|
+
# if the symbol: value notation of Hash is used, add "$" to the key
|
262
|
+
x = "$#{x.to_s}" unless x.is_a?(String) && x[0] == "$"
|
263
|
+
"#{x} = #{ case y
|
264
|
+
when self.class
|
265
|
+
"(#{y.compose})"
|
266
|
+
else
|
267
|
+
y.to_db
|
268
|
+
end }"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end.join(', ')
|
272
|
+
end
|
273
|
+
end
|
274
|
+
#
|
275
|
+
def projection value= nil # :nodoc:
|
276
|
+
if value.present?
|
277
|
+
@q[:projection] << value
|
278
|
+
self
|
279
|
+
elsif @q[:projection].present?
|
280
|
+
@q[:projection].compact.map do | s |
|
281
|
+
case s
|
282
|
+
when ::Array
|
283
|
+
s.join(', ')
|
284
|
+
when String, Symbol
|
285
|
+
s.to_s
|
286
|
+
when ::Hash
|
287
|
+
s.map{ |x,y| "#{x} as #{y}"}.join( ', ')
|
288
|
+
end
|
289
|
+
end.join( ', ' )
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def group value = nil
|
294
|
+
if value.present?
|
295
|
+
@q[:group] << value
|
296
|
+
self
|
297
|
+
elsif @q[:group].present?
|
298
|
+
"group by #{@q[:group].join(', ')}"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
alias order_by order
|
303
|
+
alias group_by group
|
304
|
+
|
305
|
+
def get_limit # :nodoc:
|
306
|
+
@q[:limit].nil? ? -1 : @q[:limit].to_i
|
307
|
+
end
|
308
|
+
|
309
|
+
def expand item
|
310
|
+
@q[:projection] =[ " expand ( #{item.to_s} )" ]
|
311
|
+
self
|
312
|
+
end
|
313
|
+
|
314
|
+
# connects by adding {in_or_out}('edgeClass')
|
315
|
+
def connect_with in_or_out, via: nil
|
316
|
+
argument = " #{in_or_out}(#{via.to_or if via.present?})"
|
317
|
+
end
|
318
|
+
# adds a connection
|
319
|
+
# in_or_out: :out ---> outE('edgeClass').in[where-condition]
|
320
|
+
# :in ---> inE('edgeClass').out[where-condition]
|
321
|
+
|
322
|
+
def nodes in_or_out = :out, via: nil, where: nil, expand: false
|
323
|
+
|
324
|
+
condition = where.present? ? "[ #{generate_sql_list(where)} ]" : ""
|
325
|
+
via = resolve_edge_name(via) unless via.nil?
|
326
|
+
|
327
|
+
start = if in_or_out.is_a? Symbol
|
328
|
+
in_or_out.to_s
|
329
|
+
elsif in_or_out.is_a? String
|
330
|
+
in_or_out
|
331
|
+
else
|
332
|
+
"both"
|
333
|
+
end
|
334
|
+
argument = " #{start}(#{via})#{condition} "
|
335
|
+
|
336
|
+
if expand.present?
|
337
|
+
send :expand, argument
|
338
|
+
else
|
339
|
+
@q[:projection] << argument
|
340
|
+
end
|
341
|
+
self
|
342
|
+
end
|
343
|
+
|
344
|
+
|
345
|
+
def query
|
346
|
+
db.query compose
|
347
|
+
end
|
348
|
+
|
349
|
+
# returns nil if the query was not sucessfully executed
|
350
|
+
def execute(reduce: false, autoload: true )
|
351
|
+
# unless projection.nil? || projection.empty?
|
352
|
+
result = db.execute { compose }
|
353
|
+
return nil unless result.is_a?(Array)
|
354
|
+
block_given? ? result.map{|x| yield x } : result
|
355
|
+
# return result.first if reduce && result.size == 1
|
356
|
+
## case select count(*) from ... --> [{ :count => n }] projection is set
|
357
|
+
## case update ... after $current --> [{ :$current => n}] projection is not set, but result is an integer
|
358
|
+
# separate key from values and get model-files
|
359
|
+
# if !@q[:projection].empty? && result.first.is_a?(Hash) && result.first.values.is_a?( Array )
|
360
|
+
# if reduce
|
361
|
+
# result.first.values.map{|x| allocate_model x, autoload}
|
362
|
+
# else
|
363
|
+
# result.map{|_,m| allocate_model m, autoload }
|
364
|
+
# end
|
365
|
+
# eloe
|
366
|
+
# result.map{|y| allocate_model y, autoload }
|
367
|
+
# end
|
368
|
+
## standard case: return Array
|
369
|
+
#result.arcade_flatten
|
370
|
+
end
|
371
|
+
:protected
|
372
|
+
def resolve_target
|
373
|
+
if @q[:database].is_a? Query
|
374
|
+
@q[:database].resolve_target
|
375
|
+
else
|
376
|
+
@q[:database]
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
# end
|
381
|
+
end # class
|
382
|
+
|
383
|
+
|
384
|
+
end # module
|
@@ -0,0 +1,295 @@
|
|
1
|
+
module Arcade
|
2
|
+
module Support
|
3
|
+
module Array
|
4
|
+
# Class extentions to manage to_db and from_db
|
5
|
+
def to_db
|
6
|
+
if all?{ |x| x.respond_to?(:rid?)} && any?( &:rid? )
|
7
|
+
"["+ map{|x| x.rid? ? x.rid : x.to_or }.join(', ') + ']'
|
8
|
+
else
|
9
|
+
map(&:to_db) # .join(',')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_or
|
14
|
+
"["+ map( &:to_or).join(', ')+"]"
|
15
|
+
end
|
16
|
+
|
17
|
+
def from_db
|
18
|
+
map &:from_db
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_human
|
22
|
+
map &:to_human
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_html
|
26
|
+
# all elements are treated equally
|
27
|
+
if first.is_a? Arcade::Base
|
28
|
+
IRuby::Table map(&:invariant_attributes)
|
29
|
+
else
|
30
|
+
IRuby.display IRuby.html "<p> #{map(&:to_human).join("<br>")}</p>"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# used to enable
|
35
|
+
# def abc *key
|
36
|
+
# where key is a Range, an comma separated List or an item
|
37
|
+
# aimed to support #compose_where
|
38
|
+
def analyse # :nodoc:
|
39
|
+
if first.is_a?(Range)
|
40
|
+
first
|
41
|
+
elsif size ==1
|
42
|
+
first
|
43
|
+
else
|
44
|
+
self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def arcade_flatten
|
49
|
+
while( first.is_a?(Array) )
|
50
|
+
self.flatten!(1)
|
51
|
+
end
|
52
|
+
self.compact!
|
53
|
+
self ## return object
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# chainable model-extaction method
|
58
|
+
#
|
59
|
+
# Used to get the results of a query where a projection is specified
|
60
|
+
# q = DB.query(" select <projection> from ...") --> [<projection> => [ { result (hash) } , ... ]]
|
61
|
+
# q.select_result( <projection> ) --> An array or plain results or
|
62
|
+
# --> an array of Arcade::Base-objects
|
63
|
+
#
|
64
|
+
|
65
|
+
def select_result condition=nil
|
66
|
+
condition = first.keys.first if condition.nil?
|
67
|
+
map{|x| x[condition.to_sym]}.flatten.allocate_model
|
68
|
+
end
|
69
|
+
|
70
|
+
# convert query results into Arcade::Base-objects
|
71
|
+
# handles [query: => [{ result }, {result} ], too
|
72
|
+
|
73
|
+
def allocate_model autoload=false
|
74
|
+
if size==1 && first.is_a?( Hash ) && !first.keys.include?( :@type )
|
75
|
+
# Load only the associated record, not the entire structure
|
76
|
+
first.values.flatten.map{ |x| x.allocate_model(false) }
|
77
|
+
else
|
78
|
+
map{ |x| _allocate_model x, autoload }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class Array
|
86
|
+
include Arcade::Support::Array
|
87
|
+
include Arcade::Support::Model # mixin allocate_model
|
88
|
+
|
89
|
+
@@accepted_methods = [:"_allocate_model"]
|
90
|
+
## dummy for refining
|
91
|
+
|
92
|
+
# it is assumed that the first element of the array acts
|
93
|
+
# as master .
|
94
|
+
def method_missing method, *args, &b
|
95
|
+
return if [:to_hash, :to_str].include? method
|
96
|
+
if @@accepted_methods.include?( method ) || first.invariant_attributes.include?( method )
|
97
|
+
self.map{ |x| x.public_send method, *args, &b }
|
98
|
+
else
|
99
|
+
raise ArgumentError.new("Method #{method} does not exist in class #{first.class}")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
module Arcade
|
106
|
+
module Support
|
107
|
+
module Symbol
|
108
|
+
def to_a
|
109
|
+
[ self ]
|
110
|
+
end
|
111
|
+
# symbols are masked with ":{symbol}:"
|
112
|
+
def to_db
|
113
|
+
":" + self.to_s + ":"
|
114
|
+
end
|
115
|
+
def to_or
|
116
|
+
"'" + self.to_db + "'"
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
module Object
|
122
|
+
def from_db
|
123
|
+
self
|
124
|
+
end
|
125
|
+
|
126
|
+
def to_db
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_or
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
def rid?
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
module Time
|
140
|
+
def to_or
|
141
|
+
"DATE(#{self.to_datetime.strftime('%Q')})"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
module Date
|
146
|
+
def to_db
|
147
|
+
if RUBY_PLATFORM == 'java'
|
148
|
+
java.util.Date.new( year-1900, month-1, day , 0, 0 , 0 ) ## Jahr 0 => 1900
|
149
|
+
else
|
150
|
+
self
|
151
|
+
end
|
152
|
+
end
|
153
|
+
def to_or
|
154
|
+
"\"#{self.to_s}\""
|
155
|
+
# "DATE(\'#{self.to_s}\',\'yyyy-MM-dd\')"
|
156
|
+
# "DATE(#{self.strftime('%Q')})"
|
157
|
+
end
|
158
|
+
# def to_json
|
159
|
+
# "DATE(#{self.strftime('%Q')})"
|
160
|
+
# end
|
161
|
+
end
|
162
|
+
module DateTime
|
163
|
+
def to_or
|
164
|
+
"DATE(#{self.strftime('%Q')})"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
module Numeric
|
168
|
+
|
169
|
+
def to_or
|
170
|
+
# "#{self.to_s}"
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
def to_a
|
175
|
+
[ self ]
|
176
|
+
end
|
177
|
+
|
178
|
+
def rid?
|
179
|
+
nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
module Hash
|
184
|
+
|
185
|
+
# converts :abc => {anything} to "abc" => {anything}
|
186
|
+
#
|
187
|
+
# converts nn => {anything} to nn => {anything}
|
188
|
+
#
|
189
|
+
# leaves "abc" => {anything} untouched
|
190
|
+
def to_db # converts hast from activeorient to db
|
191
|
+
map do | k, v|
|
192
|
+
orient_k = case k
|
193
|
+
when Numeric
|
194
|
+
k
|
195
|
+
when Symbol, String
|
196
|
+
k.to_s
|
197
|
+
else
|
198
|
+
raise "not supported key: #{k} -- must a sting, symbol or number"
|
199
|
+
end
|
200
|
+
[orient_k, v.to_db]
|
201
|
+
end.to_h
|
202
|
+
end
|
203
|
+
#
|
204
|
+
def from_db
|
205
|
+
# populate the hash by converting keys: stings to symbols, values: preprocess through :from_db
|
206
|
+
map do |k,v|
|
207
|
+
orient_k = if k.to_s.to_i.to_s == k.to_s
|
208
|
+
k.to_i
|
209
|
+
else
|
210
|
+
k.to_sym
|
211
|
+
end
|
212
|
+
|
213
|
+
[orient_k, v.from_db]
|
214
|
+
end.to_h
|
215
|
+
end
|
216
|
+
|
217
|
+
def to_human
|
218
|
+
"< " + map do | k,v |
|
219
|
+
vv = v.is_a?( Arcade::Base ) ? v.to_human[1..-2] : v.to_s
|
220
|
+
k.to_s + ": " + vv
|
221
|
+
end.join( "\n " ) + " >"
|
222
|
+
end
|
223
|
+
|
224
|
+
def allocate_model( autoload = Config.autoload )
|
225
|
+
_allocate_model( self , autoload )
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
# converts a hash to a string appropiate to include in raw queries
|
231
|
+
def to_or
|
232
|
+
"{ " + to_db.map{|k,v| "#{k.to_or}: #{v.to_or}"}.join(',') + "}"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
module String2
|
238
|
+
|
239
|
+
# from db translates the database response into active-orient objects
|
240
|
+
#
|
241
|
+
# symbols are representated via ":{something]:}"
|
242
|
+
#
|
243
|
+
# database records respond to the "rid"-method
|
244
|
+
#
|
245
|
+
# other values are not modified
|
246
|
+
def from_db
|
247
|
+
if rid?
|
248
|
+
Arcade::Init.db.get self
|
249
|
+
elsif self =~ /^:.*:$/
|
250
|
+
# symbol-representation in the database
|
251
|
+
self[1..-2].to_sym
|
252
|
+
else
|
253
|
+
self
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
alias expand from_db
|
258
|
+
# if the string contains "#xx:yy" omit quotes
|
259
|
+
def to_db
|
260
|
+
rid? ? "#"+rid : self # return the string (not the quoted string. this is to_or)
|
261
|
+
end
|
262
|
+
|
263
|
+
def to_or
|
264
|
+
quote
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
|
271
|
+
Symbol.include Arcade::Support::Symbol
|
272
|
+
Numeric.include Arcade::Support::Numeric
|
273
|
+
Object.include Arcade::Support::Object
|
274
|
+
Time.include Arcade::Support::Time
|
275
|
+
Date.include Arcade::Support::Date
|
276
|
+
DateTime.include Arcade::Support::DateTime
|
277
|
+
String.include Arcade::Support::String2
|
278
|
+
class Hash
|
279
|
+
include Arcade::Support::Model # mixin allocate_model
|
280
|
+
include Arcade::Support::Hash
|
281
|
+
end
|
282
|
+
|
283
|
+
class NilClass
|
284
|
+
def to_or
|
285
|
+
"NULL"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
|
294
|
+
|
295
|
+
|