glue 0.20.0 → 0.21.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/CHANGELOG +161 -110
- data/INSTALL +12 -12
- data/README +1 -1
- data/Rakefile +43 -45
- data/doc/AUTHORS +5 -5
- data/doc/LICENSE +3 -3
- data/doc/RELEASES +32 -24
- data/install.rb +7 -17
- data/lib/facet/object/alias_class.rb +12 -0
- data/lib/glue.rb +35 -35
- data/lib/glue/array.rb +46 -46
- data/lib/glue/aspects.rb +199 -209
- data/lib/glue/attribute.rb +15 -15
- data/lib/glue/autoreload.rb +1 -1
- data/lib/glue/builder.rb +48 -0
- data/lib/glue/builder/xml.rb +114 -0
- data/lib/glue/cache.rb +189 -0
- data/lib/glue/configuration.rb +108 -90
- data/lib/glue/flexob.rb +17 -17
- data/lib/glue/hash.rb +71 -71
- data/lib/glue/helper.rb +12 -12
- data/lib/glue/idgen.rb +9 -0
- data/lib/glue/idgen/md5.rb +24 -0
- data/lib/glue/idgen/sequential.rb +15 -0
- data/lib/glue/literal_method.rb +44 -0
- data/lib/glue/localization.rb +130 -0
- data/lib/glue/logger.rb +98 -98
- data/lib/glue/misc.rb +7 -7
- data/lib/glue/mixins.rb +19 -19
- data/lib/glue/number.rb +8 -8
- data/lib/glue/object.rb +2 -2
- data/lib/glue/pool.rb +43 -43
- data/lib/glue/property.rb +392 -392
- data/lib/glue/sanitize.rb +34 -34
- data/lib/glue/settings.rb +1 -1
- data/lib/glue/snapshot.rb +104 -0
- data/lib/glue/string.rb +129 -129
- data/lib/glue/time.rb +53 -53
- data/lib/glue/uri.rb +162 -162
- data/lib/glue/validation.rb +421 -421
- data/lib/vendor/blankslate.rb +53 -0
- data/test/glue/builder/tc_xml.rb +56 -0
- data/test/glue/tc_aspects.rb +90 -90
- data/test/glue/tc_attribute.rb +11 -11
- data/test/glue/tc_builder.rb +30 -0
- data/test/glue/tc_configuration.rb +97 -97
- data/test/glue/tc_flexob.rb +10 -10
- data/test/glue/tc_hash.rb +23 -23
- data/test/glue/tc_localization.rb +49 -0
- data/test/glue/tc_logger.rb +31 -31
- data/test/glue/tc_numbers.rb +9 -9
- data/test/glue/tc_property.rb +67 -67
- data/test/glue/tc_property_mixins.rb +17 -17
- data/test/glue/tc_property_type_checking.rb +13 -13
- data/test/glue/tc_strings.rb +94 -94
- data/test/glue/tc_uri.rb +65 -65
- data/test/glue/tc_validation.rb +196 -196
- metadata +26 -4
data/lib/glue/validation.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: validation.rb
|
3
|
+
# $Id: validation.rb 182 2005-07-22 10:07:50Z gmosx $
|
4
4
|
|
5
5
|
module Glue
|
6
6
|
|
@@ -10,11 +10,11 @@ module Glue
|
|
10
10
|
#
|
11
11
|
# The following validation macros are available:
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
13
|
+
# * validate_value
|
14
|
+
# * validate_confirmation
|
15
|
+
# * validate_format
|
16
|
+
# * validate_length
|
17
|
+
# * validate_inclusion
|
18
18
|
#
|
19
19
|
# Og/Database specific validation methods are added in the
|
20
20
|
# file og/validation.rb
|
@@ -22,37 +22,37 @@ module Glue
|
|
22
22
|
# === Example
|
23
23
|
#
|
24
24
|
# class User
|
25
|
-
#
|
26
|
-
#
|
25
|
+
# prop_accessor :name, String
|
26
|
+
# prop_accessor :level, Fixnum
|
27
27
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
28
|
+
# validate_length :name, :range => 2..6
|
29
|
+
# validate_unique :name, :msg => :name_allready_exists
|
30
|
+
# validate_format :name, :format => /[a-z]*/, :msg => 'invalid format', :on => :create
|
31
|
+
# end
|
32
32
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
33
|
+
# class CustomUserValidator
|
34
|
+
# include Validation
|
35
|
+
# validate_length :name, :range => 2..6, :msg_short => :name_too_short, :msg_long => :name_too_long
|
36
|
+
# end
|
37
37
|
#
|
38
|
-
#
|
39
|
-
#
|
38
|
+
# user = @request.fill(User.new)
|
39
|
+
# user.level = 15
|
40
40
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
41
|
+
# unless user.valid?
|
42
|
+
# user.save
|
43
|
+
# else
|
44
|
+
# p user.errors[:name]
|
45
|
+
# end
|
46
46
|
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
47
|
+
# unless user.save
|
48
|
+
# p user.errors.on(:name)
|
49
|
+
# end
|
50
50
|
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
51
|
+
# unless errors = CustomUserValidator.errors(user)
|
52
|
+
# user.save
|
53
|
+
# else
|
54
|
+
# p errors[:name]
|
55
|
+
# end
|
56
56
|
#
|
57
57
|
#--
|
58
58
|
# TODO: all validation methods should imply validate_value
|
@@ -61,401 +61,401 @@ module Glue
|
|
61
61
|
|
62
62
|
module Validation
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
64
|
+
# Encapsulates a list of validation errors.
|
65
|
+
|
66
|
+
class Errors
|
67
|
+
attr_accessor :errors
|
68
|
+
|
69
|
+
cattr_accessor :no_value, 'No value provided'
|
70
|
+
cattr_accessor :no_confirmation, 'Invalid confirmation'
|
71
|
+
cattr_accessor :invalid_format, 'Invalid format'
|
72
|
+
cattr_accessor :too_short, 'Too short, must be more than %d characters long'
|
73
|
+
cattr_accessor :too_long, 'Too long, must be less than %d characters long'
|
74
|
+
cattr_accessor :invalid_length, 'Must be %d characters long'
|
75
|
+
cattr_accessor :no_inclusion, 'The value is invalid'
|
76
|
+
cattr_accessor :no_numeric, 'The value must be numeric'
|
77
|
+
cattr_accessor :not_unique, 'The value is already used'
|
78
|
+
|
79
|
+
def initialize
|
80
|
+
@errors = {}
|
81
|
+
end
|
82
|
+
|
83
|
+
def add(attr, message)
|
84
|
+
(@errors[attr] ||= []) << message
|
85
|
+
end
|
86
|
+
|
87
|
+
def on(attr)
|
88
|
+
@errors[attr]
|
89
|
+
end
|
90
|
+
alias_method :[], :on
|
91
|
+
|
92
|
+
# Yields each attribute and associated message.
|
93
|
+
|
94
|
+
def each
|
95
|
+
@errors.each_key do |attr|
|
96
|
+
@errors[attr].each { |msg| yield attr, msg }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def size
|
101
|
+
@errors.size
|
102
|
+
end
|
103
|
+
alias_method :count, :size
|
104
|
+
|
105
|
+
def empty?
|
106
|
+
@errors.empty?
|
107
|
+
end
|
108
|
+
|
109
|
+
def clear
|
110
|
+
@errors.clear
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# If the validate method returns true, this
|
115
|
+
# attributes holds the errors found.
|
116
|
+
|
117
|
+
attr_accessor :errors
|
118
|
+
|
119
|
+
# Call the #validate method for this object.
|
120
|
+
# If validation errors are found, sets the
|
121
|
+
# @errors attribute to the Errors object and
|
122
|
+
# returns true.
|
123
|
+
|
124
|
+
def valid?
|
125
|
+
begin
|
126
|
+
@errors = self.class.validate(self)
|
127
|
+
return @errors.empty?
|
128
|
+
rescue NoMethodError => e
|
129
|
+
# gmosx: hmm this is potentially dangerous.
|
130
|
+
Glue::Validation.eval_validate(self.class)
|
131
|
+
retry
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Evaluate the 'validate' method for the calling
|
136
|
+
# class.
|
137
|
+
#
|
138
|
+
# WARNING: for the moment only evaluates for
|
139
|
+
# on == :save
|
140
|
+
|
141
|
+
def self.eval_validate(klass)
|
142
|
+
code = %{
|
143
|
+
def self.validate(obj, on = :save)
|
144
|
+
errors = Errors.new
|
145
|
+
}
|
146
|
+
|
147
|
+
for val, on in klass.__meta[:validations]
|
148
|
+
code << %{
|
149
|
+
#{val}
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
code << %{
|
154
|
+
return errors
|
155
|
+
end
|
156
|
+
}
|
157
|
+
|
158
|
+
klass.module_eval(code)
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.append_features(base)
|
162
|
+
super
|
163
|
+
|
164
|
+
base.module_eval <<-"end_eval", __FILE__, __LINE__
|
165
|
+
meta :validations, []
|
166
|
+
end_eval
|
167
|
+
|
168
|
+
base.extend(MetaLanguage)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Implements the Validation meta-language.
|
172
|
+
|
173
|
+
module MetaLanguage
|
174
|
+
|
175
|
+
# the postfix attached to confirmation attributes.
|
176
|
+
|
177
|
+
mattr_accessor :confirmation_postfix, '_confirmation'
|
178
|
+
|
179
|
+
# Validates that the attributes have a values, ie they are
|
180
|
+
# neither nil or empty.
|
181
|
+
#
|
182
|
+
# === Example
|
183
|
+
#
|
184
|
+
# validate_value :param, :msg => 'No confirmation'
|
185
|
+
|
186
|
+
def validate_value(*params)
|
187
|
+
c = {
|
188
|
+
:msg => Glue::Validation::Errors.no_value,
|
189
|
+
:on => :save
|
190
|
+
}
|
191
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
192
|
+
|
193
|
+
idx = 0
|
194
|
+
for name in params
|
195
|
+
code = %{
|
196
|
+
if obj.#{name}.nil?
|
197
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
198
|
+
elsif obj.#{name}.respond_to?(:empty?)
|
199
|
+
errors.add(:#{name}, '#{c[:msg]}') if obj.#{name}.empty?
|
200
|
+
end
|
201
|
+
}
|
202
|
+
|
203
|
+
__meta[:validations] << [code, c[:on]]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Validates the confirmation of +String+ attributes.
|
208
|
+
#
|
209
|
+
# === Example
|
210
|
+
#
|
211
|
+
# validate_confirmation :password, :msg => 'No confirmation'
|
212
|
+
|
213
|
+
def validate_confirmation(*params)
|
214
|
+
c = {
|
215
|
+
:msg => Glue::Validation::Errors.no_confirmation,
|
216
|
+
:postfix => Glue::Validation::MetaLanguage.confirmation_postfix,
|
217
|
+
:on => :save
|
218
|
+
}
|
219
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
220
|
+
|
221
|
+
|
222
|
+
for name in params
|
223
|
+
confirm_name = "#{name}#{c[:postfix]}"
|
224
|
+
eval "attr_accessor :#{confirm_name}"
|
225
|
+
|
226
|
+
code = %{
|
227
|
+
if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
|
228
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
229
|
+
end
|
230
|
+
}
|
231
|
+
|
232
|
+
__meta[:validations] << [code, c[:on]]
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# Validates the format of +String+ attributes.
|
237
|
+
# WARNING: regexp options are ignored.
|
238
|
+
#
|
239
|
+
# === Example
|
240
|
+
#
|
241
|
+
# validate_format :name, :format => /$A*/, :msg => 'My error', :on => :create
|
242
|
+
#
|
243
|
+
#--
|
244
|
+
# FIXME: how to get the Regexp options?
|
245
|
+
#++
|
246
|
+
|
247
|
+
def validate_format(*params)
|
248
|
+
c = {
|
249
|
+
:format => nil,
|
250
|
+
:msg_no_value => Glue::Validation::Errors.no_value,
|
251
|
+
:msg => Glue::Validation::Errors.invalid_format,
|
252
|
+
:on => :save
|
253
|
+
}
|
254
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
255
|
+
|
256
|
+
unless c[:format].is_a?(Regexp)
|
257
|
+
raise(ArgumentError,
|
258
|
+
'A regular expression must be supplied as the :format option')
|
259
|
+
end
|
260
|
+
|
261
|
+
for name in params
|
262
|
+
code = %{
|
263
|
+
if obj.#{name}.nil?
|
264
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
265
|
+
else
|
266
|
+
unless obj.#{name}.to_s.match(/#{c[:format].source}/)
|
267
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
268
|
+
end
|
269
|
+
end;
|
270
|
+
}
|
271
|
+
|
272
|
+
__meta[:validations] << [code, c[:on]]
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Validates the length of +String+ attributes.
|
277
|
+
#
|
278
|
+
# === Example
|
279
|
+
#
|
280
|
+
# validate_length :name, :max => 30, :msg => 'Too long'
|
281
|
+
# validate_length :name, :min => 2, :msg => 'Too sort'
|
282
|
+
# validate_length :name, :range => 2..30
|
283
|
+
# validate_length :name, :length => 15, :msg => 'Name should be %d chars long'
|
284
|
+
|
285
|
+
def validate_length(*params)
|
286
|
+
c = {
|
287
|
+
:min => nil, :max => nil, :range => nil, :length => nil,
|
288
|
+
:msg => nil,
|
289
|
+
:msg_no_value => Glue::Validation::Errors.no_value,
|
290
|
+
:msg_short => Glue::Validation::Errors.too_short,
|
291
|
+
:msg_long => Glue::Validation::Errors.too_long,
|
292
|
+
:on => :save
|
293
|
+
}
|
294
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
295
|
+
|
296
|
+
min, max = c[:min], c[:max]
|
297
|
+
range, length = c[:range], c[:length]
|
298
|
+
|
299
|
+
count = 0
|
300
|
+
[min, max, range, length].each { |o| count += 1 if o }
|
301
|
+
|
302
|
+
if count == 0
|
303
|
+
raise(ArgumentError,
|
304
|
+
'One of :min, :max, :range, :length must be provided!')
|
305
|
+
end
|
306
|
+
|
307
|
+
if count > 1
|
308
|
+
raise(ArgumentError,
|
309
|
+
'The :min, :max, :range, :length options are mutually exclusive!')
|
310
|
+
end
|
311
|
+
|
312
|
+
for name in params
|
313
|
+
if min
|
314
|
+
c[:msg] ||= Glue::Validation::Errors.too_short
|
315
|
+
code = %{
|
316
|
+
if obj.#{name}.nil?
|
317
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
318
|
+
elsif obj.#{name}.to_s.length < #{min}
|
319
|
+
msg = '#{c[:msg]}'
|
320
|
+
msg = (msg % #{min}) rescue msg
|
321
|
+
errors.add(:#{name}, msg)
|
322
|
+
end;
|
323
|
+
}
|
324
|
+
elsif max
|
325
|
+
c[:msg] ||= Glue::Validation::Errors.too_long
|
326
|
+
code = %{
|
327
|
+
if obj.#{name}.nil?
|
328
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
329
|
+
elsif obj.#{name}.to_s.length > #{max}
|
330
|
+
msg = '#{c[:msg]}'
|
331
|
+
msg = (msg % #{max}) rescue msg
|
332
|
+
errors.add(:#{name}, msg)
|
333
|
+
end;
|
334
|
+
}
|
335
|
+
elsif range
|
336
|
+
code = %{
|
337
|
+
if obj.#{name}.nil?
|
338
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
339
|
+
elsif obj.#{name}.to_s.length < #{range.first}
|
340
|
+
msg = '#{c[:msg_short]}'
|
341
|
+
msg = (msg % #{range.first}) rescue msg
|
342
|
+
errors.add(:#{name}, msg)
|
343
|
+
elsif obj.#{name}.to_s.length > #{range.last}
|
344
|
+
msg = '#{c[:msg_long]}'
|
345
|
+
msg = (msg % #{range.last}) rescue msg
|
346
|
+
errors.add(:#{name}, msg)
|
347
|
+
end;
|
348
|
+
}
|
349
|
+
elsif length
|
350
|
+
c[:msg] ||= Glue::Validation::Errors.invalid_length
|
351
|
+
code = %{
|
352
|
+
if obj.#{name}.nil?
|
353
|
+
errors.add(:#{name}, '#{c[:msg_no_value]}')
|
354
|
+
elsif obj.#{name}.to_s.length != #{length}
|
355
|
+
msg = '#{c[:msg]}'
|
356
|
+
msg = (msg % #{length}) rescue msg
|
357
|
+
errors.add(:#{name}, msg)
|
358
|
+
end;
|
359
|
+
}
|
360
|
+
end
|
361
|
+
|
362
|
+
__meta[:validations] << [code, c[:on]]
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# Validates that the attributes are included in
|
367
|
+
# an enumeration.
|
368
|
+
#
|
369
|
+
# === Example
|
370
|
+
#
|
371
|
+
# validate_inclusion :sex, :in => %w{ Male Female }, :msg => 'huh??'
|
372
|
+
# validate_inclusion :age, :in => 5..99
|
373
|
+
|
374
|
+
def validate_inclusion(*params)
|
375
|
+
c = {
|
376
|
+
:in => nil,
|
377
|
+
:msg => Glue::Validation::Errors.no_inclusion,
|
378
|
+
:allow_nil => false,
|
379
|
+
:on => :save
|
380
|
+
}
|
381
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
382
|
+
|
383
|
+
unless c[:in].respond_to?('include?')
|
384
|
+
raise(ArgumentError,
|
385
|
+
'An object that responds to #include? must be supplied as the :in option')
|
386
|
+
end
|
387
|
+
|
388
|
+
for name in params
|
389
|
+
if c[:allow_nil]
|
390
|
+
code = %{
|
391
|
+
unless obj.#{name}.nil? or (#{c[:in].inspect}).include?(obj.#{name})
|
392
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
393
|
+
end;
|
394
|
+
}
|
395
|
+
else
|
396
|
+
code = %{
|
397
|
+
unless (#{c[:in].inspect}).include?(obj.#{name})
|
398
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
399
|
+
end;
|
400
|
+
}
|
401
|
+
end
|
402
|
+
|
403
|
+
__meta[:validations] << [code, c[:on]]
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# Validates that the attributes have numeric values.
|
408
|
+
#
|
409
|
+
# [+:integer+]
|
410
|
+
# Only accept integers
|
411
|
+
#
|
412
|
+
# [+:msg]
|
413
|
+
# Custom message
|
414
|
+
#
|
415
|
+
# [+:on:]
|
416
|
+
# When to validate
|
417
|
+
#
|
418
|
+
# === Example
|
419
|
+
#
|
420
|
+
# validate_numeric :age, :msg => 'Must be an integer'
|
421
|
+
|
422
|
+
def validate_numeric(*params)
|
423
|
+
c = {
|
424
|
+
:integer => false,
|
425
|
+
:msg => Glue::Validation::Errors.no_numeric,
|
426
|
+
:on => :save
|
427
|
+
}
|
428
|
+
c.update(params.pop) if params.last.is_a?(Hash)
|
429
|
+
|
430
|
+
for name in params
|
431
|
+
if c[:integer]
|
432
|
+
code = %{
|
433
|
+
unless obj.#{name}.to_s =~ /^[\\+\\-]?\\d+$/
|
434
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
435
|
+
end;
|
436
|
+
}
|
437
|
+
else
|
438
|
+
code = %{
|
439
|
+
begin
|
440
|
+
Kernel.Float(obj.#{name})
|
441
|
+
rescue ArgumentError, TypeError
|
442
|
+
errors.add(:#{name}, '#{c[:msg]}')
|
443
|
+
end;
|
444
|
+
}
|
445
|
+
end
|
446
|
+
|
447
|
+
__meta[:validations] << [code, c[:on]]
|
448
|
+
end
|
449
|
+
end
|
450
|
+
alias_method :validate_numericality, :validate_numeric
|
451
|
+
|
452
|
+
end
|
453
453
|
|
454
454
|
end
|
455
455
|
|
456
456
|
end
|
457
457
|
|
458
458
|
class Module # :nodoc: all
|
459
|
-
|
459
|
+
include Glue::Validation::MetaLanguage
|
460
460
|
end
|
461
461
|
|