og 0.12.0 → 0.13.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.
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