og 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGELOG +27 -0
  2. data/INSTALL +56 -0
  3. data/{README.og → README} +3 -3
  4. data/Rakefile +7 -73
  5. data/benchmark/bench.rb +75 -0
  6. data/benchmark/sqlite-no-prepare.1.txt +13 -0
  7. data/benchmark/sqlite-no-prepare.2.txt +13 -0
  8. data/benchmark/sqlite-prepare.1.txt +13 -0
  9. data/benchmark/sqlite-prepare.2.txt +13 -0
  10. data/doc/AUTHORS +0 -9
  11. data/{RELEASES.og → doc/RELEASES} +15 -0
  12. data/doc/config.txt +35 -0
  13. data/doc/tutorial.txt +595 -0
  14. data/examples/{og/README → README} +1 -1
  15. data/examples/{og/mock_example.rb → mock_example.rb} +1 -1
  16. data/examples/{og/mysql_to_psql.rb → mysql_to_psql.rb} +1 -1
  17. data/examples/{og/run.rb → run.rb} +1 -1
  18. data/install.rb +8 -5
  19. data/lib/og.rb +13 -8
  20. data/lib/og/adapter.rb +1 -1
  21. data/lib/og/adapters/filesys.rb +1 -1
  22. data/lib/og/adapters/mysql.rb +4 -3
  23. data/lib/og/adapters/oracle.rb +1 -1
  24. data/lib/og/adapters/psql.rb +4 -3
  25. data/lib/og/adapters/sqlite.rb +1 -1
  26. data/lib/og/backend.rb +1 -1
  27. data/lib/og/connection.rb +1 -1
  28. data/lib/og/database.rb +1 -1
  29. data/lib/og/meta.rb +13 -2
  30. data/lib/og/observer.rb +1 -1
  31. data/lib/og/typemacros.rb +1 -1
  32. data/lib/og/validation.rb +81 -0
  33. data/test/og/tc_validation.rb +89 -0
  34. metadata +33 -65
  35. data/ChangeLog +0 -1549
  36. data/lib/glue.rb +0 -55
  37. data/lib/glue/array.rb +0 -61
  38. data/lib/glue/attribute.rb +0 -83
  39. data/lib/glue/cache.rb +0 -138
  40. data/lib/glue/flexob.rb +0 -12
  41. data/lib/glue/hash.rb +0 -122
  42. data/lib/glue/inflector.rb +0 -91
  43. data/lib/glue/logger.rb +0 -147
  44. data/lib/glue/misc.rb +0 -14
  45. data/lib/glue/mixins.rb +0 -36
  46. data/lib/glue/number.rb +0 -24
  47. data/lib/glue/object.rb +0 -32
  48. data/lib/glue/pool.rb +0 -60
  49. data/lib/glue/property.rb +0 -408
  50. data/lib/glue/string.rb +0 -162
  51. data/lib/glue/time.rb +0 -85
  52. data/lib/glue/validation.rb +0 -394
  53. data/vendor/extensions/_base.rb +0 -153
  54. data/vendor/extensions/_template.rb +0 -36
  55. data/vendor/extensions/all.rb +0 -21
  56. data/vendor/extensions/array.rb +0 -68
  57. data/vendor/extensions/binding.rb +0 -224
  58. data/vendor/extensions/class.rb +0 -50
  59. data/vendor/extensions/continuation.rb +0 -71
  60. data/vendor/extensions/enumerable.rb +0 -250
  61. data/vendor/extensions/hash.rb +0 -23
  62. data/vendor/extensions/io.rb +0 -58
  63. data/vendor/extensions/kernel.rb +0 -42
  64. data/vendor/extensions/module.rb +0 -114
  65. data/vendor/extensions/numeric.rb +0 -230
  66. data/vendor/extensions/object.rb +0 -164
  67. data/vendor/extensions/ostruct.rb +0 -41
  68. data/vendor/extensions/string.rb +0 -316
  69. data/vendor/extensions/symbol.rb +0 -28
@@ -1,162 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # * Anastasios Koutoumanos <ak@navel.gr>
3
- # * Elias Karakoulakis <ekarak@ktismata.com>
4
- # (c) 2004-2005 Navel, all rights reserved.
5
- # $Id: string.rb 259 2005-02-15 08:54:54Z gmosx $
6
-
7
- require "uri"
8
-
9
- module N;
10
-
11
- # General string utilities collection.
12
- #
13
- # === Design:
14
- #
15
- # Implement as a module to avoid class polution. You can
16
- # still Ruby's advanced features to include the module in your
17
- # class. Passing the object to act upon allows to check for nil,
18
- # which isn't possible if you use self.
19
- #
20
- # === TODO:
21
- #
22
- # - implement a method that returns easy to remember
23
- # pseudo-random strings
24
- # - add aliases for those methods in Kernel.
25
-
26
- module StringUtils
27
-
28
- # Move this in String class?
29
- #
30
- # Tests a string for a valid value (non nil, not empty)
31
- #
32
- def self.valid?(string)
33
- return (not ((nil == string) or (string.empty?)))
34
- end
35
-
36
- # returns short abstract of long strings (first 'count'
37
- # characters, chopped at the nearest word, appended by '...')
38
- # force_cutoff: break forcibly at 'count' chars. Does not accept
39
- # count < 2.
40
-
41
- def self.head(string, count = 128, force_cutoff = false, ellipsis="...")
42
- return nil unless string
43
- return nil if count < 2
44
-
45
- if string.size > count
46
- cut_at = force_cutoff ? count : (string.index(' ', count-1) || count)
47
- xstring = string.slice(0, cut_at)
48
- return xstring.chomp(" ") + ellipsis
49
- else
50
- return string
51
- end
52
- end
53
-
54
- # Apply a set of rules (regular expression matches) to the
55
- # string
56
- #
57
- # === Requirements:
58
- # - the rules must be applied in order! So we cannot use a
59
- # hash because the ordering is not guaranteed! we use an
60
- # array instead.
61
- #
62
- # === Input:
63
- # the string to rewrite
64
- # the array containing rule-pairs (match, rewrite)
65
- #
66
- # === Output:
67
- # the rewritten string
68
-
69
- MATCH = 0
70
- REWRITE = 1
71
-
72
- def self.rewrite(string, rules)
73
- return nil unless string
74
-
75
- # gmosx: helps to find bugs
76
- raise ArgumentError.new('The rules parameter is nil') unless rules
77
-
78
- rewritten_string = string.dup
79
-
80
- for rule in rules
81
- rewritten_string.gsub!(rule[MATCH], rule[REWRITE])
82
- end
83
-
84
- return (rewritten_string or string)
85
- end
86
-
87
- # Enforces a maximum width of a string inside an
88
- # html container. If the string exceeds this maximum width
89
- # the string gets wraped.
90
- #
91
- # Not really useful, better use the CSS overflow: hidden
92
- # functionality.
93
- #
94
- # === Input:
95
- # the string to be wrapped
96
- # the enforced width
97
- # the separator used for wrapping
98
- #
99
- # === Output:
100
- # the wrapped string
101
- #
102
- # === Example:
103
- # text = "1111111111111111111111111111111111111111111"
104
- # text = wrap(text, 10, " ")
105
- # p text # => "1111111111 1111111111 1111111111"
106
- #
107
- # See the test cases to better understand the behaviour!
108
-
109
- def self.wrap(string, width = 20, separator = " ")
110
- return nil unless string
111
-
112
- re = /([^#{separator}]{1,#{width}})/
113
- wrapped_string = string.scan(re).join(separator)
114
-
115
- return wrapped_string
116
- end
117
-
118
- # Replace dangerours chars in filenames
119
- =begin
120
- def self.rationalize_filename(filename)
121
- return nil unless filename
122
- # gmosx: rationalize a copy!!! (add unit test)
123
- xfilename = filename.dup()
124
- # gmosx: replace some dangerous chars!
125
- xfilename.gsub!(/ /, "-")
126
- xfilename.gsub!(/!/, "")
127
- xfilename.gsub!(/'/, "")
128
- xfilename.gsub!(/\(/, "")
129
- xfilename.gsub!(/\)/, "")
130
- # xfilename = self.to_greeklish(xfilename)
131
- return xfilename
132
- end
133
- =end
134
-
135
- # Returns a random string. one possible use is
136
- # password initialization.
137
- #
138
- # === Input:
139
- # the maximum length of the string
140
- #
141
- # === Output:
142
- # the random string
143
-
144
- def self.random(max_length = 8, char_re = /[\w\d]/)
145
- # gmosx: this is a nice example of input parameter checking.
146
- # this is NOT a real time called method so we can add this
147
- # check. Congrats to the author.
148
- raise ArgumentError.new('char_re must be a regular expression!') unless char_re.is_a?(Regexp)
149
-
150
- string = ""
151
-
152
- while string.length < max_length
153
- ch = rand(255).chr
154
- string << ch if ch =~ char_re
155
- end
156
-
157
- return string
158
- end
159
-
160
- end
161
-
162
- end
@@ -1,85 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: time.rb 259 2005-02-15 08:54:54Z gmosx $
4
-
5
- require 'time.rb'
6
-
7
- module N;
8
-
9
- # General time utilities collection
10
- #
11
- # Implement as a module to avoid class polution. You can
12
- # still Ruby's advanced features to include the module in your
13
- # class. Passing the object to act upon allows to check for nil,
14
- # which isn't possible if you use self.
15
- #
16
- # == TODO
17
- #
18
- # - SOS: add test units.
19
- # - add aliases for those methods in Kernel ?
20
-
21
- module TimeUtils
22
-
23
- NOW = Time.now
24
- NEVER = Time.mktime(2038)
25
- ZERO = Time.mktime(1972)
26
-
27
- # Convert the time to a nice String representation.
28
-
29
- def self.date_time(time)
30
- return nil unless time
31
- return time.strftime("%d-%m-%Y %H:%M")
32
- end
33
-
34
- # This method calculates the days extrema given two time objects.
35
- # start time is the given time1 at 00:00:00
36
- # end time is the given time2 at 23:59:59:999
37
- #
38
- # Input:
39
- # - the two times (if only time1 is provided then you get an extrema
40
- # of exactly one day extrema.
41
- #
42
- # Output
43
- # - the time range. you can get the start/end times using
44
- # range methods.
45
-
46
- def self.days_extrema(time1, time2=nil)
47
- time2 = time1 if (not time2.valid? Time)
48
- time2 = NEVER if (time2 <= time1)
49
- start_time = Time.self.start_of_day(time1)
50
- end_time = self.end_of_day(time2)
51
- return (start_time..end_time)
52
- end
53
-
54
- # Set time to start of day
55
-
56
- def self.start_of_day(time)
57
- return Time.mktime(time.year, time.month, time.day, 0, 0, 0, 0)
58
- end
59
-
60
-
61
- # Set time to end of day
62
-
63
- def self.end_of_day(time)
64
- return Time.mktime(time.year, time.month, time.day, 23, 59, 59, 999)
65
- end
66
-
67
-
68
- # Returns true only if day of time is included in the
69
- # range (stime..etime). Only year days are checked.
70
-
71
- def self.time_in_day_range(time, stime=ZERO, etime=NEVER)
72
- if (etime <= stime)
73
- Logger.debug "Invalid end time (#{etime} < #{stime})" if $DBG
74
- etime = NEVER
75
- end
76
-
77
- stime = start_of_day(stime)
78
- etime = end_of_day(etime)
79
-
80
- return (stime..etime).include?(time)
81
- end
82
-
83
- end
84
-
85
- end
@@ -1,394 +0,0 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id$
4
-
5
- module N
6
-
7
- # Implements a meta-language for validating managed
8
- # objects. Typically used in Validator objects but can be
9
- # included in managed objects too.
10
- #
11
- # === Example
12
- #
13
- # class User
14
- # prop_accessor :name, String
15
- # prop_accessor :level, Fixnum
16
- #
17
- # validate_length :name, :range => 2..6
18
- # validate_unique :name, :msg => :name_allready_exists
19
- # validate_format :name, :format => /[a-z]*/, :msg => 'invalid format', :on => :create
20
- # end
21
- #
22
- # class N::CustomUserValidator
23
- # include N::Validation
24
- # validate_length :name, :range => 2..6, :msg_short => :name_too_short, :msg_long => :name_too_long
25
- # end
26
- #
27
- # user = @request.fill(User.new)
28
- # user.level = 15
29
- #
30
- # unless user.valid?
31
- # user.save
32
- # else
33
- # p user.errors[:name]
34
- # end
35
- #
36
- # unless user.save
37
- # p user.errors.on(:name)
38
- # end
39
- #
40
- # unless errors = N::CustomUserValidator.errors(user)
41
- # user.save
42
- # else
43
- # p errors[:name]
44
- # end
45
- #
46
- #--
47
- # TODO: all validation methods should imply validate_value
48
- # TODO: add validate_unique
49
- #++
50
-
51
- module Validation
52
-
53
- # Encapsulates a list of validation errors.
54
-
55
- class Errors
56
- attr_accessor :errors
57
-
58
- cattr_accessor :no_value, 'No value provided'
59
- cattr_accessor :no_confirmation, 'Invalid confirmation'
60
- cattr_accessor :invalid_format, 'Invalid format'
61
- cattr_accessor :too_short, 'Too short, must be more than %d characters long'
62
- cattr_accessor :too_long, 'Too long, must be less than %d characters long'
63
- cattr_accessor :invalid_length, 'Must be %d characters long'
64
- cattr_accessor :no_inclusion, 'The value is invalid'
65
-
66
- def initialize
67
- @errors = {}
68
- end
69
-
70
- def add(attr, message)
71
- (@errors[attr] ||= []) << message
72
- end
73
-
74
- def on(attr)
75
- @errors[attr]
76
- end
77
- alias_method :[], :on
78
-
79
- # Yields each attribute and associated message.
80
-
81
- def each
82
- @errors.each_key do |attr|
83
- @errors[attr].each { |msg| yield attr, msg }
84
- end
85
- end
86
-
87
- def size
88
- @errors.size
89
- end
90
- alias_method :count, :size
91
-
92
- def empty?
93
- @errors.empty?
94
- end
95
-
96
- def clear
97
- @errors.clear
98
- end
99
- end
100
-
101
- # If the validate method returns true, this
102
- # attributes holds the errors found.
103
-
104
- attr_accessor :errors
105
-
106
- # Call the #validate method for this object.
107
- # If validation errors are found, sets the
108
- # @errors attribute to the Errors object and
109
- # returns true.
110
-
111
- def valid?
112
- begin
113
- @errors = self.class.validate(self)
114
- return @errors.empty?
115
- rescue NoMethodError => e
116
- # gmosx: hmm this is potentially dangerous.
117
- N::Validation.eval_validate(self.class)
118
- retry
119
- end
120
- end
121
-
122
- # Evaluate the 'validate' method for the calling
123
- # class.
124
- #
125
- # WARNING: for the moment only evaluates for
126
- # on == :save
127
-
128
- def self.eval_validate(klass)
129
- code = %{
130
- def self.validate(obj, on = :save)
131
- errors = Errors.new
132
- }
133
-
134
- for val, on in klass.__meta[:validations]
135
- code << %{
136
- #{val}
137
- }
138
- end
139
-
140
- code << %{
141
- return errors
142
- end
143
- }
144
-
145
- # puts '-->', code, '<--'
146
-
147
- klass.module_eval(code)
148
- end
149
-
150
- def self.append_features(base)
151
- super
152
-
153
- base.module_eval <<-"end_eval", __FILE__, __LINE__
154
- meta :validations, []
155
- end_eval
156
-
157
- base.extend(MetaLanguage)
158
- end
159
-
160
- # Implements the Validation meta-language.
161
-
162
- module MetaLanguage
163
-
164
- # the postfix attached to confirmation attributes.
165
-
166
- mattr_accessor :confirmation_postfix, '_confirmation'
167
-
168
- # Validates that the attributes have a values, ie they are
169
- # neither nil or empty.
170
- #
171
- # === Example
172
- #
173
- # validate_value :param, :msg => 'No confirmation'
174
-
175
- def validate_value(*params)
176
- c = {
177
- :msg => N::Validation::Errors.no_value,
178
- :on => :save
179
- }
180
- c.update(params.pop) if params.last.is_a?(Hash)
181
-
182
- idx = 0
183
- for name in params
184
- code = %{
185
- if obj.#{name}.nil?
186
- errors.add(:#{name}, '#{c[:msg]}')
187
- elsif obj.#{name}.respond_to?(:empty?)
188
- errors.add(:#{name}, '#{c[:msg]}') if obj.#{name}.empty?
189
- end
190
- }
191
-
192
- __meta[:validations] << [code, c[:on]]
193
- end
194
- end
195
-
196
- # Validates the confirmation of +String+ attributes.
197
- #
198
- # === Example
199
- #
200
- # validate_confirmation :password, :msg => 'No confirmation'
201
-
202
- def validate_confirmation(*params)
203
- c = {
204
- :msg => N::Validation::Errors.no_confirmation,
205
- :postfix => N::Validation::MetaLanguage.confirmation_postfix,
206
- :on => :save
207
- }
208
- c.update(params.pop) if params.last.is_a?(Hash)
209
-
210
-
211
- for name in params
212
- confirm_name = "#{name}#{c[:postfix]}"
213
- eval "attr_accessor :#{confirm_name}"
214
-
215
- code = %{
216
- if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
217
- errors.add(:#{name}, '#{c[:msg]}')
218
- end
219
- }
220
-
221
- __meta[:validations] << [code, c[:on]]
222
- end
223
- end
224
-
225
- # Validates the format of +String+ attributes.
226
- #
227
- # === Example
228
- #
229
- # validate_format :name, :format => /$A*/, :msg => 'My error', :on => :create
230
-
231
- def validate_format(*params)
232
- c = {
233
- :format => nil,
234
- :msg_no_value => N::Validation::Errors.no_value,
235
- :msg => N::Validation::Errors.invalid_format,
236
- :on => :save
237
- }
238
- c.update(params.pop) if params.last.is_a?(Hash)
239
-
240
- unless c[:format].is_a?(Regexp)
241
- raise(ArgumentError,
242
- 'A regular expression must be supplied as the :format option')
243
- end
244
-
245
- for name in params
246
- code = %{
247
- if obj.#{name}.nil?
248
- errors.add(:#{name}, '#{c[:msg_no_value]}')
249
- else
250
- unless obj.#{name}.to_s.match(/#{Regexp.quote(c[:format].source)}/)
251
- errors.add(:#{name}, '#{c[:msg]}')
252
- end
253
- end;
254
- }
255
-
256
- __meta[:validations] << [code, c[:on]]
257
- end
258
- end
259
-
260
- # Validates the length of +String+ attributes.
261
- #
262
- # === Example
263
- #
264
- # validate_length :name, :max => 30, :msg => 'Too long'
265
- # validate_length :name, :min => 2, :msg => 'Too sort'
266
- # validate_length :name, :range => 2..30
267
- # validate_length :name, :length => 15, :msg => 'Name should be %d chars long'
268
-
269
- def validate_length(*params)
270
- c = {
271
- :min => nil, :max => nil, :range => nil, :length => nil,
272
- :msg => nil,
273
- :msg_no_value => N::Validation::Errors.no_value,
274
- :msg_short => N::Validation::Errors.too_short,
275
- :msg_long => N::Validation::Errors.too_long,
276
- :on => :save
277
- }
278
- c.update(params.pop) if params.last.is_a?(Hash)
279
-
280
- min, max = c[:min], c[:max]
281
- range, length = c[:range], c[:length]
282
-
283
- count = 0
284
- [min, max, range, length].each { |o| count += 1 if o }
285
-
286
- if count == 0
287
- raise(ArgumentError,
288
- 'One of :min, :max, :range, :length must be provided!')
289
- end
290
-
291
- if count > 1
292
- raise(ArgumentError,
293
- 'The :min, :max, :range, :length options are mutually exclusive!')
294
- end
295
-
296
- for name in params
297
- if min
298
- c[:msg] ||= N::Validation::Errors.too_short
299
- code = %{
300
- if obj.#{name}.nil?
301
- errors.add(:#{name}, '#{c[:msg_no_value]}')
302
- elsif obj.#{name}.to_s.length < #{min}
303
- msg = '#{c[:msg]}'
304
- msg = (msg % #{min}) rescue msg
305
- errors.add(:#{name}, msg)
306
- end;
307
- }
308
- elsif max
309
- c[:msg] ||= N::Validation::Errors.too_long
310
- code = %{
311
- if obj.#{name}.nil?
312
- errors.add(:#{name}, '#{c[:msg_no_value]}')
313
- elsif obj.#{name}.to_s.length > #{max}
314
- msg = '#{c[:msg]}'
315
- msg = (msg % #{max}) rescue msg
316
- errors.add(:#{name}, msg)
317
- end;
318
- }
319
- elsif range
320
- code = %{
321
- if obj.#{name}.nil?
322
- errors.add(:#{name}, '#{c[:msg_no_value]}')
323
- elsif obj.#{name}.to_s.length < #{range.first}
324
- msg = '#{c[:msg_short]}'
325
- msg = (msg % #{range.first}) rescue msg
326
- errors.add(:#{name}, msg)
327
- elsif obj.#{name}.to_s.length > #{range.last}
328
- msg = '#{c[:msg_long]}'
329
- msg = (msg % #{range.last}) rescue msg
330
- errors.add(:#{name}, msg)
331
- end;
332
- }
333
- elsif length
334
- c[:msg] ||= N::Validation::Errors.invalid_length
335
- code = %{
336
- if obj.#{name}.nil?
337
- errors.add(:#{name}, '#{c[:msg_no_value]}')
338
- elsif obj.#{name}.to_s.length != #{length}
339
- msg = '#{c[:msg]}'
340
- msg = (msg % #{length}) rescue msg
341
- errors.add(:#{name}, msg)
342
- end;
343
- }
344
- end
345
-
346
- __meta[:validations] << [code, c[:on]]
347
- end
348
- end
349
-
350
- # Validates that the attributes are included in
351
- # an enumeration.
352
- #
353
- # === Example
354
- #
355
- # validate_inclusion :sex, :in => %w{ Male Female }, :msg => 'huh??'
356
- # validate_inclusion :age, :in => 5..99
357
-
358
- def validate_inclusion(*params)
359
- c = {
360
- :in => nil,
361
- :msg => N::Validation::Errors.no_inclusion,
362
- :allow_nil => false,
363
- :on => :save
364
- }
365
- c.update(params.pop) if params.last.is_a?(Hash)
366
-
367
- unless c[:in].respond_to?('include?')
368
- raise(ArgumentError,
369
- 'An object that responds to #include? must be supplied as the :in option')
370
- end
371
-
372
- for name in params
373
- if c[:allow_nil]
374
- code = %{
375
- unless obj.#{name}.nil? or (#{c[:in].inspect}).include?(obj.#{name})
376
- errors.add(:#{name}, '#{c[:msg]}')
377
- end;
378
- }
379
- else
380
- code = %{
381
- unless (#{c[:in].inspect}).include?(obj.#{name})
382
- errors.add(:#{name}, '#{c[:msg]}')
383
- end;
384
- }
385
- end
386
-
387
- __meta[:validations] << [code, c[:on]]
388
- end
389
- end
390
-
391
- end
392
- end
393
-
394
- end