arcadedb 0.3.1 → 0.3.3
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 +4 -4
- data/.gitignore +57 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +168 -0
- data/Guardfile +30 -0
- data/LICENSE +21 -0
- data/README.md +242 -0
- data/Rakefile +11 -0
- data/arcade.yml +27 -0
- data/arcadedb.gemspec +35 -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 +306 -0
- data/lib/arcade/api/version.rb +5 -0
- data/lib/arcade/base.rb +455 -0
- data/lib/arcade/database.rb +338 -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 +39 -0
- data/lib/config.rb +70 -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 +84 -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 +49 -4
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 Arcade::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? Arcade::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
|
+
|