og 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +27 -0
- data/INSTALL +56 -0
- data/{README.og → README} +3 -3
- data/Rakefile +7 -73
- data/benchmark/bench.rb +75 -0
- data/benchmark/sqlite-no-prepare.1.txt +13 -0
- data/benchmark/sqlite-no-prepare.2.txt +13 -0
- data/benchmark/sqlite-prepare.1.txt +13 -0
- data/benchmark/sqlite-prepare.2.txt +13 -0
- data/doc/AUTHORS +0 -9
- data/{RELEASES.og → doc/RELEASES} +15 -0
- data/doc/config.txt +35 -0
- data/doc/tutorial.txt +595 -0
- data/examples/{og/README → README} +1 -1
- data/examples/{og/mock_example.rb → mock_example.rb} +1 -1
- data/examples/{og/mysql_to_psql.rb → mysql_to_psql.rb} +1 -1
- data/examples/{og/run.rb → run.rb} +1 -1
- data/install.rb +8 -5
- data/lib/og.rb +13 -8
- data/lib/og/adapter.rb +1 -1
- data/lib/og/adapters/filesys.rb +1 -1
- data/lib/og/adapters/mysql.rb +4 -3
- data/lib/og/adapters/oracle.rb +1 -1
- data/lib/og/adapters/psql.rb +4 -3
- data/lib/og/adapters/sqlite.rb +1 -1
- data/lib/og/backend.rb +1 -1
- data/lib/og/connection.rb +1 -1
- data/lib/og/database.rb +1 -1
- data/lib/og/meta.rb +13 -2
- data/lib/og/observer.rb +1 -1
- data/lib/og/typemacros.rb +1 -1
- data/lib/og/validation.rb +81 -0
- data/test/og/tc_validation.rb +89 -0
- metadata +33 -65
- data/ChangeLog +0 -1549
- data/lib/glue.rb +0 -55
- data/lib/glue/array.rb +0 -61
- data/lib/glue/attribute.rb +0 -83
- data/lib/glue/cache.rb +0 -138
- data/lib/glue/flexob.rb +0 -12
- data/lib/glue/hash.rb +0 -122
- data/lib/glue/inflector.rb +0 -91
- data/lib/glue/logger.rb +0 -147
- data/lib/glue/misc.rb +0 -14
- data/lib/glue/mixins.rb +0 -36
- data/lib/glue/number.rb +0 -24
- data/lib/glue/object.rb +0 -32
- data/lib/glue/pool.rb +0 -60
- data/lib/glue/property.rb +0 -408
- data/lib/glue/string.rb +0 -162
- data/lib/glue/time.rb +0 -85
- data/lib/glue/validation.rb +0 -394
- data/vendor/extensions/_base.rb +0 -153
- data/vendor/extensions/_template.rb +0 -36
- data/vendor/extensions/all.rb +0 -21
- data/vendor/extensions/array.rb +0 -68
- data/vendor/extensions/binding.rb +0 -224
- data/vendor/extensions/class.rb +0 -50
- data/vendor/extensions/continuation.rb +0 -71
- data/vendor/extensions/enumerable.rb +0 -250
- data/vendor/extensions/hash.rb +0 -23
- data/vendor/extensions/io.rb +0 -58
- data/vendor/extensions/kernel.rb +0 -42
- data/vendor/extensions/module.rb +0 -114
- data/vendor/extensions/numeric.rb +0 -230
- data/vendor/extensions/object.rb +0 -164
- data/vendor/extensions/ostruct.rb +0 -41
- data/vendor/extensions/string.rb +0 -316
- data/vendor/extensions/symbol.rb +0 -28
data/lib/glue/string.rb
DELETED
@@ -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
|
data/lib/glue/time.rb
DELETED
@@ -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
|
data/lib/glue/validation.rb
DELETED
@@ -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
|