og 0.7.0 → 0.8.0
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.
- data/AUTHORS +14 -4
- data/ChangeLog +192 -1
- data/README.og +2 -1
- data/RELEASES.og +35 -0
- data/Rakefile +1 -1
- data/examples/og/mock_example.rb +6 -9
- data/examples/og/mysql_to_psql.rb +100 -0
- data/examples/og/run.rb +8 -17
- data/lib/glue/array.rb +1 -1
- data/lib/glue/attribute.rb +86 -0
- data/lib/glue/cache.rb +1 -1
- data/lib/glue/hash.rb +1 -1
- data/lib/glue/inflector.rb +1 -1
- data/lib/glue/logger.rb +118 -18
- data/lib/glue/mixins.rb +1 -1
- data/lib/glue/number.rb +1 -1
- data/lib/glue/pool.rb +1 -1
- data/lib/glue/property.rb +48 -31
- data/lib/glue/string.rb +1 -1
- data/lib/glue/time.rb +2 -2
- data/lib/glue/validation.rb +400 -0
- data/lib/glue.rb +7 -8
- data/lib/og/backend.rb +47 -46
- data/lib/og/backends/mysql.rb +64 -63
- data/lib/og/backends/psql.rb +73 -72
- data/lib/og/connection.rb +7 -8
- data/lib/og/enchant.rb +80 -0
- data/lib/og/meta.rb +21 -21
- data/lib/og/mock.rb +31 -88
- data/lib/og/version.rb +6 -5
- data/lib/og.rb +95 -129
- data/test/tc_og.rb +3 -3
- data/vendor/extensions/_base.rb +153 -0
- data/vendor/extensions/_template.rb +36 -0
- data/vendor/extensions/all.rb +21 -0
- data/vendor/extensions/array.rb +68 -0
- data/vendor/extensions/binding.rb +224 -0
- data/vendor/extensions/class.rb +50 -0
- data/vendor/extensions/continuation.rb +71 -0
- data/vendor/extensions/enumerable.rb +250 -0
- data/vendor/extensions/hash.rb +23 -0
- data/vendor/extensions/io.rb +58 -0
- data/vendor/extensions/kernel.rb +42 -0
- data/vendor/extensions/module.rb +114 -0
- data/vendor/extensions/numeric.rb +230 -0
- data/vendor/extensions/object.rb +164 -0
- data/vendor/extensions/ostruct.rb +41 -0
- data/vendor/extensions/string.rb +316 -0
- data/vendor/extensions/symbol.rb +28 -0
- metadata +24 -4
- data/lib/glue/property.rb.old +0 -307
@@ -0,0 +1,400 @@
|
|
1
|
+
# George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2005 Navel, all rights reserved.
|
3
|
+
# $Id$
|
4
|
+
|
5
|
+
module N
|
6
|
+
|
7
|
+
# = Validation
|
8
|
+
#
|
9
|
+
# Implements a meta-language for validating managed
|
10
|
+
# objects. Typically used in Validator objects but can be
|
11
|
+
# included in managed objects too.
|
12
|
+
#
|
13
|
+
# == Example
|
14
|
+
#
|
15
|
+
# class User
|
16
|
+
# prop_accessor :name, String
|
17
|
+
# prop_accessor :level, Fixnum
|
18
|
+
#
|
19
|
+
# validate_length :name, :range => 2..6
|
20
|
+
# validate_unique :name, :msg => :name_allready_exists
|
21
|
+
# validate_format :name, :format => /[a-z]*/, :msg => 'invalid format', :on => :create
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# class N::CustomUserValidator
|
25
|
+
# include N::Validation
|
26
|
+
# validate_length :name, :range => 2..6, :msg_short => :name_too_short, :msg_long => :name_too_long
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# user = @request.fill(User.new)
|
30
|
+
# user.level = 15
|
31
|
+
#
|
32
|
+
# unless user.valid?
|
33
|
+
# user.save
|
34
|
+
# else
|
35
|
+
# p user.errors[:name]
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# unless user.save
|
39
|
+
# p user.errors.on(:name)
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# unless errors = N::CustomUserValidator.errors(user)
|
43
|
+
# user.save
|
44
|
+
# else
|
45
|
+
# p errors[:name]
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
#--
|
49
|
+
# TODO: all validation methods should imply validate_value
|
50
|
+
# TODO: add validate_unique
|
51
|
+
#++
|
52
|
+
|
53
|
+
module Validation
|
54
|
+
|
55
|
+
# = Errors
|
56
|
+
#
|
57
|
+
# Encapsulates a list of validation errors.
|
58
|
+
|
59
|
+
class Errors
|
60
|
+
attr_accessor :errors
|
61
|
+
|
62
|
+
cattr_accessor :no_value, 'No value provided'
|
63
|
+
cattr_accessor :no_confirmation, 'Invalid confirmation'
|
64
|
+
cattr_accessor :invalid_format, 'Invalid format'
|
65
|
+
cattr_accessor :too_short, 'Too short, must be more than %d characters long'
|
66
|
+
cattr_accessor :too_long, 'Too long, must be less than %d characters long'
|
67
|
+
cattr_accessor :invalid_length, 'Must be %d characters long'
|
68
|
+
cattr_accessor :no_inclusion, 'The value is invalid'
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
@errors = {}
|
72
|
+
end
|
73
|
+
|
74
|
+
def add(attr, message)
|
75
|
+
(@errors[attr] ||= []) << message
|
76
|
+
end
|
77
|
+
|
78
|
+
def on(attr)
|
79
|
+
@errors[attr]
|
80
|
+
end
|
81
|
+
alias_method :[], :on
|
82
|
+
|
83
|
+
# Yields each attribute and associated message.
|
84
|
+
|
85
|
+
def each
|
86
|
+
@errors.each_key do |attr|
|
87
|
+
@errors[attr].each { |msg| yield attr, msg }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def size
|
92
|
+
@errors.size
|
93
|
+
end
|
94
|
+
alias_method :count, :size
|
95
|
+
|
96
|
+
def empty?
|
97
|
+
@errors.empty?
|
98
|
+
end
|
99
|
+
|
100
|
+
def clear
|
101
|
+
@errors.clear
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# If the validate method returns true, this
|
106
|
+
# attributes holds the errors found.
|
107
|
+
|
108
|
+
attr_accessor :errors
|
109
|
+
|
110
|
+
# Call the #validate method for this object.
|
111
|
+
# If validation errors are found, sets the
|
112
|
+
# @errors attribute to the Errors object and
|
113
|
+
# returns true.
|
114
|
+
|
115
|
+
def valid?
|
116
|
+
begin
|
117
|
+
@errors = self.class.validate(self)
|
118
|
+
return @errors.empty?
|
119
|
+
rescue NoMethodError => e
|
120
|
+
# gmosx: hmm this is potentially dangerous.
|
121
|
+
N::Validation.eval_validate(self.class)
|
122
|
+
retry
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Evaluate the 'validate' method for the calling
|
127
|
+
# class.
|
128
|
+
#
|
129
|
+
# WARNING: for the moment only evaluates for
|
130
|
+
# on == :save
|
131
|
+
|
132
|
+
def self.eval_validate(klass)
|
133
|
+
code = %{
|
134
|
+
def self.validate(obj, on = :save)
|
135
|
+
errors = Errors.new
|
136
|
+
}
|
137
|
+
|
138
|
+
for val, on in klass.__meta[:validations]
|
139
|
+
code << %{
|
140
|
+
#{val}
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
code << %{
|
145
|
+
return errors
|
146
|
+
end
|
147
|
+
}
|
148
|
+
|
149
|
+
# puts '-->', code, '<--'
|
150
|
+
|
151
|
+
klass.module_eval(code)
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.append_features(base)
|
155
|
+
super
|
156
|
+
|
157
|
+
base.module_eval <<-"end_eval", __FILE__, __LINE__
|
158
|
+
meta :validations, []
|
159
|
+
end_eval
|
160
|
+
|
161
|
+
base.extend(MetaLanguage)
|
162
|
+
end
|
163
|
+
|
164
|
+
# = MetaLanguage
|
165
|
+
#
|
166
|
+
# Implements the Validation meta-language.
|
167
|
+
|
168
|
+
module MetaLanguage
|
169
|
+
|
170
|
+
# the postfix attached to confirmation attributes.
|
171
|
+
|
172
|
+
mattr_accessor :confirmation_postfix, '_confirmation'
|
173
|
+
|
174
|
+
# Validates that the attributes have a values, ie they are
|
175
|
+
# neither nil or empty.
|
176
|
+
#
|
177
|
+
# == Example
|
178
|
+
#
|
179
|
+
# validate_value :, :msg => 'No confirmation'
|
180
|
+
|
181
|
+
def validate_value(*params)
|
182
|
+
c = {
|
183
|
+
:msg => N::Validation::Errors.no_value,
|
184
|
+
:on => :save
|
185
|
+
}
|
186
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
187
|
+
|
188
|
+
idx = 0
|
189
|
+
for name in params
|
190
|
+
code = %{
|
191
|
+
if obj.#{name}.nil?
|
192
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
193
|
+
elsif obj.#{name}.respond_to?(:empty?)
|
194
|
+
errors.add(:#{name}, '#{c[:msg]}') if obj.#{name}.empty?
|
195
|
+
end
|
196
|
+
}
|
197
|
+
|
198
|
+
__meta[:validations] << [code, c[:on]]
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Validates the confirmation of +String+ attributes.
|
203
|
+
#
|
204
|
+
# == Example
|
205
|
+
#
|
206
|
+
# validate_confirmation :password, :msg => 'No confirmation'
|
207
|
+
|
208
|
+
def validate_confirmation(*params)
|
209
|
+
c = {
|
210
|
+
:msg => N::Validation::Errors.no_confirmation,
|
211
|
+
:postfix => N::Validation::MetaLanguage.confirmation_postfix,
|
212
|
+
:on => :save
|
213
|
+
}
|
214
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
215
|
+
|
216
|
+
|
217
|
+
for name in params
|
218
|
+
confirm_name = "#{name}#{c[:postfix]}"
|
219
|
+
attr_accessor :"#{confirm_name}"
|
220
|
+
|
221
|
+
code = %{
|
222
|
+
if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
|
223
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
224
|
+
end
|
225
|
+
}
|
226
|
+
|
227
|
+
__meta[:validations] << [code, c[:on]]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Validates the format of +String+ attributes.
|
232
|
+
#
|
233
|
+
# == Example
|
234
|
+
#
|
235
|
+
# validate_format :name, :format => /$A*/, :msg => 'My error', :on => :create
|
236
|
+
|
237
|
+
def validate_format(*params)
|
238
|
+
c = {
|
239
|
+
:format => nil,
|
240
|
+
:msg_no_value => N::Validation::Errors.no_value,
|
241
|
+
:msg => N::Validation::Errors.invalid_format,
|
242
|
+
:on => :save
|
243
|
+
}
|
244
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
245
|
+
|
246
|
+
unless c[:format].is_a?(Regexp)
|
247
|
+
raise(ArgumentError,
|
248
|
+
'A regular expression must be supplied as the :format option')
|
249
|
+
end
|
250
|
+
|
251
|
+
for name in params
|
252
|
+
code = %{
|
253
|
+
if obj.#{name}.nil?
|
254
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
255
|
+
else
|
256
|
+
unless obj.#{name}.to_s.match(/#{Regexp.quote(c[:format].source)}/)
|
257
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
258
|
+
end
|
259
|
+
end;
|
260
|
+
}
|
261
|
+
|
262
|
+
__meta[:validations] << [code, c[:on]]
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Validates the length of +String+ attributes.
|
267
|
+
#
|
268
|
+
# == Example
|
269
|
+
#
|
270
|
+
# validate_length :name, :max => 30, :msg => 'Too long'
|
271
|
+
# validate_length :name, :min => 2, :msg => 'Too sort'
|
272
|
+
# validate_length :name, :range => 2..30
|
273
|
+
# validate_length :name, :length => 15, :msg => 'Name should be %d chars long'
|
274
|
+
|
275
|
+
def validate_length(*params)
|
276
|
+
c = {
|
277
|
+
:min => nil, :max => nil, :range => nil, :length => nil,
|
278
|
+
:msg => nil,
|
279
|
+
:msg_no_value => N::Validation::Errors.no_value,
|
280
|
+
:msg_short => N::Validation::Errors.too_short,
|
281
|
+
:msg_long => N::Validation::Errors.too_long,
|
282
|
+
:on => :save
|
283
|
+
}
|
284
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
285
|
+
|
286
|
+
min, max = c[:min], c[:max]
|
287
|
+
range, length = c[:range], c[:length]
|
288
|
+
|
289
|
+
count = 0
|
290
|
+
[min, max, range, length].each { |o| count += 1 if o }
|
291
|
+
|
292
|
+
if count == 0
|
293
|
+
raise(ArgumentError,
|
294
|
+
'One of :min, :max, :range, :length must be provided!')
|
295
|
+
end
|
296
|
+
|
297
|
+
if count > 1
|
298
|
+
raise(ArgumentError,
|
299
|
+
'The :min, :max, :range, :length options are mutually exclusive!')
|
300
|
+
end
|
301
|
+
|
302
|
+
for name in params
|
303
|
+
if min
|
304
|
+
c[:msg] ||= N::Validation::Errors.too_short
|
305
|
+
code = %{
|
306
|
+
if obj.#{name}.nil?
|
307
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
308
|
+
elsif obj.#{name}.to_s.length < #{min}
|
309
|
+
msg = '#{c[:msg]}'
|
310
|
+
msg = (msg % #{min}) rescue msg
|
311
|
+
errors.add(:#{name}, msg)
|
312
|
+
end;
|
313
|
+
}
|
314
|
+
elsif max
|
315
|
+
c[:msg] ||= N::Validation::Errors.too_long
|
316
|
+
code = %{
|
317
|
+
if obj.#{name}.nil?
|
318
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
319
|
+
elsif obj.#{name}.to_s.length > #{max}
|
320
|
+
msg = '#{c[:msg]}'
|
321
|
+
msg = (msg % #{max}) rescue msg
|
322
|
+
errors.add(:#{name}, msg)
|
323
|
+
end;
|
324
|
+
}
|
325
|
+
elsif range
|
326
|
+
code = %{
|
327
|
+
if obj.#{name}.nil?
|
328
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
329
|
+
elsif obj.#{name}.to_s.length < #{range.first}
|
330
|
+
msg = '#{c[:msg_short]}'
|
331
|
+
msg = (msg % #{range.first}) rescue msg
|
332
|
+
errors.add(:#{name}, msg)
|
333
|
+
elsif obj.#{name}.to_s.length > #{range.last}
|
334
|
+
msg = '#{c[:msg_long]}'
|
335
|
+
msg = (msg % #{range.last}) rescue msg
|
336
|
+
errors.add(:#{name}, msg)
|
337
|
+
end;
|
338
|
+
}
|
339
|
+
elsif length
|
340
|
+
c[:msg] ||= N::Validation::Errors.invalid_length
|
341
|
+
code = %{
|
342
|
+
if obj.#{name}.nil?
|
343
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
344
|
+
elsif obj.#{name}.to_s.length != #{length}
|
345
|
+
msg = '#{c[:msg]}'
|
346
|
+
msg = (msg % #{length}) rescue msg
|
347
|
+
errors.add(:#{name}, msg)
|
348
|
+
end;
|
349
|
+
}
|
350
|
+
end
|
351
|
+
|
352
|
+
__meta[:validations] << [code, c[:on]]
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
# Validates that the attributes are included in
|
357
|
+
# an enumeration.
|
358
|
+
#
|
359
|
+
# == Example
|
360
|
+
#
|
361
|
+
# validate_inclusion :sex, :in => %w{ Male Female }, :msg => 'huh??'
|
362
|
+
# validate_inclusion :age, :in => 5..99
|
363
|
+
|
364
|
+
def validate_inclusion(*params)
|
365
|
+
c = {
|
366
|
+
:in => nil,
|
367
|
+
:msg => N::Validation::Errors.no_inclusion,
|
368
|
+
:allow_nil => false,
|
369
|
+
:on => :save
|
370
|
+
}
|
371
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
372
|
+
|
373
|
+
unless c[:in].respond_to?('include?')
|
374
|
+
raise(ArgumentError,
|
375
|
+
'An object that responds to #include? must be supplied as the :in option')
|
376
|
+
end
|
377
|
+
|
378
|
+
for name in params
|
379
|
+
if c[:allow_nil]
|
380
|
+
code = %{
|
381
|
+
unless obj.#{name}.nil? or (#{c[:in].inspect}).include?(obj.#{name})
|
382
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
383
|
+
end;
|
384
|
+
}
|
385
|
+
else
|
386
|
+
code = %{
|
387
|
+
unless (#{c[:in].inspect}).include?(obj.#{name})
|
388
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
389
|
+
end;
|
390
|
+
}
|
391
|
+
end
|
392
|
+
|
393
|
+
__meta[:validations] << [code, c[:on]]
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
end
|
data/lib/glue.rb
CHANGED
@@ -5,13 +5,14 @@
|
|
5
5
|
# code:
|
6
6
|
# * George Moschovitis <gm@navel.gr>
|
7
7
|
#
|
8
|
-
# (c) 2004 Navel, all rights reserved.
|
8
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
9
9
|
# $Id: glue.rb 175 2004-11-26 16:11:27Z gmosx $
|
10
10
|
|
11
|
-
require
|
12
|
-
require
|
11
|
+
require 'English'
|
12
|
+
require 'pp'
|
13
13
|
|
14
14
|
require 'glue/property'
|
15
|
+
require 'glue/attribute'
|
15
16
|
|
16
17
|
class NilClass
|
17
18
|
# quite usefull for error tolerant apps.
|
@@ -26,12 +27,13 @@ class Class
|
|
26
27
|
#--
|
27
28
|
# gmosx: is this really needed?
|
28
29
|
#++
|
29
|
-
def to_i
|
30
|
-
return self.hash
|
30
|
+
def to_i
|
31
|
+
return self.hash
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
35
|
module Kernel
|
36
|
+
|
35
37
|
# pretty prints an exception/error object
|
36
38
|
# usefull for helpfull debug messages
|
37
39
|
#
|
@@ -47,6 +49,3 @@ module Kernel
|
|
47
49
|
|
48
50
|
end
|
49
51
|
|
50
|
-
# predefine some comonly used objects
|
51
|
-
|
52
|
-
EMPTY_STRING = ""
|
data/lib/og/backend.rb
CHANGED
@@ -8,33 +8,54 @@ require "yaml"
|
|
8
8
|
|
9
9
|
require "og/connection"
|
10
10
|
|
11
|
-
|
11
|
+
class Og
|
12
12
|
|
13
|
-
# =
|
13
|
+
# = Backend
|
14
14
|
#
|
15
|
-
# A
|
15
|
+
# Abstract backend. A backend communicates with the RDBMS.
|
16
|
+
# This is the base class for the various backend implementations.
|
16
17
|
#
|
17
|
-
|
18
|
+
class Backend
|
19
|
+
|
20
|
+
# The actual connection to the database
|
21
|
+
attr_accessor :conn
|
22
|
+
|
23
|
+
# Intitialize the connection to the RDBMS.
|
24
|
+
#
|
25
|
+
def initialize(config)
|
26
|
+
raise "Not implemented"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Close the connection to the RDBMS.
|
30
|
+
#
|
31
|
+
def close()
|
32
|
+
@conn.close()
|
33
|
+
end
|
34
|
+
|
35
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
36
|
+
# Utilities
|
37
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
18
38
|
|
19
39
|
# Encode the name of the klass as an sql safe string.
|
20
|
-
# The Module separators are replaced with _ and NOT stripped
|
21
|
-
# that we can convert back to the original notation if
|
22
|
-
# The leading module if available is removed.
|
40
|
+
# The Module separators are replaced with _ and NOT stripped
|
41
|
+
# out so that we can convert back to the original notation if
|
42
|
+
# needed. The leading module if available is removed.
|
23
43
|
#
|
24
44
|
def self.encode(klass)
|
25
45
|
"#{klass.name.gsub(/^.*::/, "")}".gsub(/::/, "_").downcase
|
26
46
|
end
|
27
47
|
|
28
|
-
# The name of the SQL table where objects of this class
|
48
|
+
# The name of the SQL table where objects of this class
|
49
|
+
# are stored.
|
29
50
|
#
|
30
51
|
def self.table(klass)
|
31
|
-
"_#{
|
52
|
+
"_#{Og.table_prefix}#{encode(klass)}"
|
32
53
|
end
|
33
54
|
|
34
55
|
# The name of the join table for the two given classes.
|
35
56
|
#
|
36
57
|
def self.join_table(klass1, klass2)
|
37
|
-
"_#{
|
58
|
+
"_#{Og.table_prefix}j_#{encode(klass1)}_#{encode(klass2)}"
|
38
59
|
end
|
39
60
|
|
40
61
|
# Returns the props that will be included in the insert query.
|
@@ -123,8 +144,8 @@ module Utils
|
|
123
144
|
end
|
124
145
|
|
125
146
|
# Precompile the code to read objects of the given class
|
126
|
-
# from the backend. In order to allow for changing
|
127
|
-
# orders we have to use a field mapping hash.
|
147
|
+
# from the backend. In order to allow for changing
|
148
|
+
# field/attribute orders we have to use a field mapping hash.
|
128
149
|
#
|
129
150
|
def self.eval_og_deserialize(klass, og)
|
130
151
|
calc_field_index(klass, og)
|
@@ -136,7 +157,7 @@ module Utils
|
|
136
157
|
if idx = og.managed_classes[klass].field_index[p.name]
|
137
158
|
# more fault tolerant if a new field is added and it
|
138
159
|
# doesnt exist in the database.
|
139
|
-
code << "@#{p.name} = #{
|
160
|
+
code << "@#{p.name} = #{read_prop(p, idx)}"
|
140
161
|
end
|
141
162
|
end
|
142
163
|
|
@@ -147,40 +168,20 @@ module Utils
|
|
147
168
|
}
|
148
169
|
end
|
149
170
|
|
150
|
-
|
151
|
-
|
152
|
-
#
|
153
|
-
#
|
154
|
-
# Abstract backend. A backend communicates with the RDBMS.
|
155
|
-
# This is the base class for the various backend implementations.
|
156
|
-
#
|
157
|
-
class Backend
|
158
|
-
|
159
|
-
# The actual connection to the database
|
160
|
-
attr_accessor :conn
|
161
|
-
|
162
|
-
# Intitialize the connection to the RDBMS.
|
163
|
-
#
|
164
|
-
def initialize(config)
|
165
|
-
raise "Not implemented"
|
166
|
-
end
|
167
|
-
|
168
|
-
# Close the connection to the RDBMS.
|
169
|
-
#
|
170
|
-
def close()
|
171
|
-
@conn.close()
|
172
|
-
end
|
171
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
172
|
+
# Connection methods.
|
173
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
173
174
|
|
174
175
|
# Create the database.
|
175
176
|
#
|
176
177
|
def self.create_db(database, user = nil, password = nil)
|
177
|
-
|
178
|
+
Logger.info "Creating database '#{database}'."
|
178
179
|
end
|
179
180
|
|
180
181
|
# Drop the database.
|
181
182
|
#
|
182
183
|
def self.drop_db(database, user = nil, password = nil)
|
183
|
-
|
184
|
+
Logger.info "Dropping database '#{database}'."
|
184
185
|
end
|
185
186
|
|
186
187
|
# Execute an SQL query and return the result.
|
@@ -195,15 +196,15 @@ class Backend
|
|
195
196
|
raise "Not implemented"
|
196
197
|
end
|
197
198
|
|
198
|
-
# Execute an SQL query and return the result. Wrapped in a
|
199
|
-
# block.
|
199
|
+
# Execute an SQL query and return the result. Wrapped in a
|
200
|
+
# rescue block.
|
200
201
|
#
|
201
202
|
def safe_query(sql)
|
202
203
|
raise "Not implemented"
|
203
204
|
end
|
204
205
|
|
205
|
-
# Execute an SQL query, no result returned. Wrapped in a
|
206
|
-
# block.
|
206
|
+
# Execute an SQL query, no result returned. Wrapped in a
|
207
|
+
# rescue block.
|
207
208
|
#
|
208
209
|
def safe_exec(sql)
|
209
210
|
raise "Not implemented"
|
@@ -235,9 +236,9 @@ class Backend
|
|
235
236
|
|
236
237
|
# Create the fields that correpsond to the klass properties.
|
237
238
|
# The generated fields array is used in create_table.
|
238
|
-
# If the property has an :sql metadata this overrides the
|
239
|
-
# If the property has an :extra_sql metadata
|
240
|
-
# after the default mapping.
|
239
|
+
# If the property has an :sql metadata this overrides the
|
240
|
+
# default mapping. If the property has an :extra_sql metadata
|
241
|
+
# the extra sql is appended after the default mapping.
|
241
242
|
#
|
242
243
|
def create_fields(klass, typemap)
|
243
244
|
fields = []
|
@@ -297,4 +298,4 @@ class Backend
|
|
297
298
|
|
298
299
|
end
|
299
300
|
|
300
|
-
end #
|
301
|
+
end # namespace
|