tmtm-stringvalidator 0.4
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/lib/stringvalidator.rb +322 -0
- metadata +54 -0
@@ -0,0 +1,322 @@
|
|
1
|
+
# Copyright (C) 2007-2009 TOMITA Masahiro
|
2
|
+
# mailto:tommy@tmtm.org
|
3
|
+
#
|
4
|
+
# = StringValidator
|
5
|
+
# Author:: TOMITA Masahiro <tommy@tmtm.org>
|
6
|
+
# License:: Ruby's. see http://www.ruby-lang.org/en/LICENSE.txt
|
7
|
+
#
|
8
|
+
# * 文字列が規則に従うかどうかを検査する
|
9
|
+
# * 規則は Ruby のリテラルで記述する。
|
10
|
+
#
|
11
|
+
# == Download
|
12
|
+
# * http://github.com/tmtm/stringvalidator/downloads
|
13
|
+
#
|
14
|
+
# == Install
|
15
|
+
# $ make
|
16
|
+
# $ make test
|
17
|
+
# # make install
|
18
|
+
#
|
19
|
+
# == Usage
|
20
|
+
# StringValidator.validate(_rule_, _str_) は _str_ が _rule_ に適合していれば、_rule_ に適したオブジェクトを返す。
|
21
|
+
# 適合しなければ StringValidator::Error 例外が発生する。
|
22
|
+
#
|
23
|
+
# StringValidator.validate "abc", "abc" # => "abc"
|
24
|
+
# StringValidator.validate /hoge/, "ahoge" # => "ahoge"
|
25
|
+
# StringValidator.validate Integer, "123" # => 123
|
26
|
+
# StringValidator.validate 123, "123" # => 123
|
27
|
+
# StringValidator.validate 1..255, "128" # => 128
|
28
|
+
# StringValidator.validate 1.0..255, "10.9" # => 10.9
|
29
|
+
# str = "abc"
|
30
|
+
# StringValidator.validate ["abc", "def"], str # => str
|
31
|
+
# StringValidator.validate({:length=>3..10}, str) # => str
|
32
|
+
# StringValidator.validate({:minlength=>3, :rule=>/abc/}, str) # => str
|
33
|
+
# StringValidator.validate Proc.new{|a| a == "abc" && 999}, str # =>999
|
34
|
+
# StringValidator.validate Proc.new{|s| Date.parse s}, "2007-10-02" # => Date object
|
35
|
+
#
|
36
|
+
# StringValidator.valid?(_rule_, _str_) は _str_ が _rule_ に適合していれば true、そうでなければ false を返す。
|
37
|
+
#
|
38
|
+
# 複数ルールの定義
|
39
|
+
#
|
40
|
+
# rules = {
|
41
|
+
# :port => 1..65535,
|
42
|
+
# :domain => /\A[a-z0-9-]+(\.[a-z0-9-]+)+\z/i,
|
43
|
+
# }
|
44
|
+
# v = StringValidator.new rules
|
45
|
+
# v.valid? :port, "8080"
|
46
|
+
# v.valid? :domain, "tmtm.org"
|
47
|
+
#
|
48
|
+
# どのルールが適合したか
|
49
|
+
#
|
50
|
+
# rules = {
|
51
|
+
# :port => 1..65535,
|
52
|
+
# :domain => /\A[a-z0-9]+(\.[a-z0-9]+)+\z/i
|
53
|
+
# }
|
54
|
+
# v = StringValidator.new rules
|
55
|
+
# v.validated_rule "8080" # => :port
|
56
|
+
# v.validated_rule "tmtm.org" # => :domain
|
57
|
+
# v.validated_rule "xyz" # => nil
|
58
|
+
|
59
|
+
# == 文字列の正当性チェック
|
60
|
+
class StringValidator
|
61
|
+
# エラーの基底クラス
|
62
|
+
class Error < StandardError
|
63
|
+
# _value_:: 対象文字列
|
64
|
+
# _rule_:: ルールオブジェクト
|
65
|
+
def initialize(value=nil, rule=nil)
|
66
|
+
@rule = rule
|
67
|
+
@value = value
|
68
|
+
super self.class.errmsg
|
69
|
+
end
|
70
|
+
attr_reader :rule, :value
|
71
|
+
|
72
|
+
def self.errmsg()
|
73
|
+
@errmsg
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Integer に適合しない場合
|
78
|
+
class Error::NotInteger < Error
|
79
|
+
@errmsg = "not integer"
|
80
|
+
end
|
81
|
+
# Float に適合しない場合
|
82
|
+
class Error::NotFloat < Error
|
83
|
+
@errmsg = "not float"
|
84
|
+
end
|
85
|
+
# Range に適合しない場合
|
86
|
+
class Error::OutOfRange < Error
|
87
|
+
@errmsg = "out of range"
|
88
|
+
end
|
89
|
+
# Array, Proc, Class に適合しない場合
|
90
|
+
class Error::InvalidValue < Error
|
91
|
+
@errmsg = "invalid value"
|
92
|
+
end
|
93
|
+
# Regexp に適合しない場合
|
94
|
+
class Error::RegexpMismatch < Error
|
95
|
+
@errmsg = "regexp mismatch"
|
96
|
+
end
|
97
|
+
# Hash(:length, :charlength) に適合しない場合
|
98
|
+
class Error::InvalidLength < Error
|
99
|
+
@errmsg = "invalid length"
|
100
|
+
end
|
101
|
+
# Hash(:minlength, :mincharlength) に適合しない場合
|
102
|
+
class Error::TooShort < Error
|
103
|
+
@errmsg = "too short"
|
104
|
+
end
|
105
|
+
# Hash(:maxlength, :maxcharlength) に適合しない場合
|
106
|
+
class Error::TooLong < Error
|
107
|
+
@errmsg = "too long"
|
108
|
+
end
|
109
|
+
|
110
|
+
# _rule_:: ルールオブジェクト
|
111
|
+
# _str_:: 対象文字列
|
112
|
+
#
|
113
|
+
# _str_ が _rule_ に適合するか検査する。
|
114
|
+
# 適合しない場合、StringValidator::Error 例外が発生する。
|
115
|
+
#
|
116
|
+
# StringValidator#validate(_rule_, _str_) と同じ。
|
117
|
+
#
|
118
|
+
def self.validate(rule, str)
|
119
|
+
self.new(nil).validate(rule, str)
|
120
|
+
end
|
121
|
+
|
122
|
+
# _rule_:: ルールオブジェクト
|
123
|
+
# _str_:: 対象文字列
|
124
|
+
#
|
125
|
+
# validate(_rule_, _str_) が成功すれば true, そうでなければ false を返す。
|
126
|
+
#
|
127
|
+
def self.valid?(rule, str)
|
128
|
+
begin
|
129
|
+
self.validate(rule, str)
|
130
|
+
rescue Error
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
return true
|
134
|
+
end
|
135
|
+
|
136
|
+
# _rule_:: Hash オブジェクト。{:key => rule_object, ...}
|
137
|
+
def initialize(rule)
|
138
|
+
@rule = rule
|
139
|
+
end
|
140
|
+
|
141
|
+
# _rule_:: ルールキー。initialize に与えた Hash のキー
|
142
|
+
# _str_:: 対象文字列
|
143
|
+
#
|
144
|
+
# _str_ が _rule_ に適合するか検査する。
|
145
|
+
# 適合しない場合、StringValidator::Error 例外が発生する。
|
146
|
+
#
|
147
|
+
# === _rule_ の形式
|
148
|
+
#
|
149
|
+
# ==== Integer (Integer そのもの。Integer オブジェクトではない)
|
150
|
+
# Integer(_str_) が成功した場合に _str_ を正当とみなす。
|
151
|
+
# Integer オブジェクトを返す。
|
152
|
+
# ==== Float (Float そのもの。Float オブジェクトではない)
|
153
|
+
# Float(_str_) が成功した場合に _str_ を正当とみなす。
|
154
|
+
# Float オブジェクトを返す。
|
155
|
+
# ==== Range オブジェクト
|
156
|
+
# _rule_ が _str_ を含んでいれば _str_ を正当とみなす。
|
157
|
+
# _rule_ に応じて、Integer, Float, String オブジェクトを返す。
|
158
|
+
# ==== Regexp オブジェクト
|
159
|
+
# _str_ が _rule_ に適合すれば _str_ を正当とみなす。
|
160
|
+
# _str_ を返す。
|
161
|
+
# ==== Proc オブジェクト
|
162
|
+
# _rule_.call(_str_) が例外を発生しなければ _str_ を正当とみなす。
|
163
|
+
# _rule_.call(_str_) の結果を返す。
|
164
|
+
# ==== Array オブジェクト
|
165
|
+
# _rule_ の要素をルールとして評価し、正当な要素が一つでもあれば正当とみなす。
|
166
|
+
# 最初に正当になったルールの結果を返す。
|
167
|
+
# ==== Hash オブジェクト
|
168
|
+
# 複数のルールが指定された場合は、すべてのルールを満たせば正当とみなす。
|
169
|
+
# 結果は、:rule(なければ :any, :all)の評価結果。:rule, :any, :all のいずれもなければ str が評価結果となる。
|
170
|
+
# [<tt>:any => _array_</tt>]
|
171
|
+
# Array と同じ。
|
172
|
+
# [<tt>:all => _array_</tt>]
|
173
|
+
# _array_ の要素をルールとして評価し、すべての要素が正当であれば正当とみなす。
|
174
|
+
# 評価結果は、最初の要素のルールの評価結果。
|
175
|
+
# [<tt>:rule => _obj_</tt>]
|
176
|
+
# _obj_ をルールとして評価する。
|
177
|
+
# [<tt>:length => _integer_ or _range_</tt>]
|
178
|
+
# _str_ の長さ(バイト数)が _integer_ に一致する場合、または _range_ 内であれば正当とみなす。
|
179
|
+
# [<tt>:maxlength => _integer_</tt>]
|
180
|
+
# _str_ の長さ(バイト数)が _integer_ 以下であれば正当とみなす。
|
181
|
+
# [<tt>:minlength => _integer_</tt>]
|
182
|
+
# _str_ の長さ(バイト数)が _integer_ 以上であれば正当とみなす。
|
183
|
+
# [<tt>:charlength => _integer_ or _range_</tt>]
|
184
|
+
# _str_ の長さ(文字数)が _integer_ に一致する場合、または _range_ 内であれば正当とみなす。文字数は $KCODE に依存する。
|
185
|
+
# [<tt>:maxcharlength => _integer_</tt>]
|
186
|
+
# _str_ の長さ(文字数)が _integer_ 以下であれば正当とみなす。文字数は $KCODE に依存する。
|
187
|
+
# [<tt>:mincharlength => _integer_</tt>]
|
188
|
+
# _str_ の長さ(文字数)が _integer_ 以上であれば正当とみなす。文字数は $KCODE に依存する。
|
189
|
+
# ==== Symbol オブジェクト
|
190
|
+
# new の引数として渡したハッシュの、キー _rule_ に対応する値をルールとして評価する。
|
191
|
+
# ==== Class オブジェクト
|
192
|
+
# _rule_.new(_str_) が成功すれば正当とみなす。
|
193
|
+
# _rule_.new(_str_) を返す。
|
194
|
+
# ==== other
|
195
|
+
# _str_ が _rule_.to_s と等しければ正当とみなす。
|
196
|
+
# _rule_ を返す。
|
197
|
+
#
|
198
|
+
def validate(rule, str)
|
199
|
+
if rule == Integer then
|
200
|
+
begin
|
201
|
+
return Integer(str)
|
202
|
+
rescue ArgumentError
|
203
|
+
raise Error::NotInteger.new(str, rule)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
if rule == Float then
|
207
|
+
begin
|
208
|
+
return Float(str)
|
209
|
+
rescue ArgumentError
|
210
|
+
raise Error::NotFloat.new(str, rule)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
case rule
|
214
|
+
when Range then
|
215
|
+
if rule.first.is_a? Integer and rule.last.is_a? Integer then
|
216
|
+
validate(Integer, str)
|
217
|
+
raise Error::OutOfRange.new(str, rule) unless rule.include?(str.to_i)
|
218
|
+
return str.to_i
|
219
|
+
elsif rule.first.is_a? Numeric then
|
220
|
+
validate(Float, str)
|
221
|
+
raise Error::OutOfRange.new(str, rule) unless rule.include?(str.to_f)
|
222
|
+
return str.to_f
|
223
|
+
end
|
224
|
+
raise Error::OutOfRange.new(str, rule) unless rule.include?(str)
|
225
|
+
return str
|
226
|
+
when Regexp then
|
227
|
+
raise Error::RegexpMismatch.new(str, rule) unless rule =~ str
|
228
|
+
return str
|
229
|
+
when Proc then
|
230
|
+
begin
|
231
|
+
return rule.call(str)
|
232
|
+
rescue
|
233
|
+
raise Error::InvalidValue.new(str, rule)
|
234
|
+
end
|
235
|
+
return ret if ret
|
236
|
+
when Array then
|
237
|
+
rule.each do |i|
|
238
|
+
begin
|
239
|
+
return self.validate(i, str)
|
240
|
+
rescue Error
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
end
|
244
|
+
raise Error::InvalidValue.new(str, rule)
|
245
|
+
when Hash then
|
246
|
+
ret = {}
|
247
|
+
rule.each do |k,v|
|
248
|
+
case k
|
249
|
+
when :any
|
250
|
+
ret[k] = self.validate(v, str)
|
251
|
+
when :all
|
252
|
+
ret[k] = v.map{|i| self.validate(i, str)}.first
|
253
|
+
when :rule
|
254
|
+
ret[k] = self.validate(v, str)
|
255
|
+
when :length
|
256
|
+
begin
|
257
|
+
self.validate v, str.length.to_s
|
258
|
+
rescue Error
|
259
|
+
raise Error::InvalidLength.new(str, rule)
|
260
|
+
end
|
261
|
+
when :maxlength
|
262
|
+
raise Error::TooLong.new(str, rule) unless str.length <= v
|
263
|
+
when :minlength
|
264
|
+
raise Error::TooShort.new(str, rule) unless str.length >= v
|
265
|
+
when :charlength
|
266
|
+
begin
|
267
|
+
self.validate v, str.split(//).length.to_s
|
268
|
+
rescue Error
|
269
|
+
raise Error::InvalidLength.new(str, rule)
|
270
|
+
end
|
271
|
+
when :maxcharlength
|
272
|
+
raise Error::TooLong.new(str, rule) unless str.split(//).length <= v
|
273
|
+
when :mincharlength
|
274
|
+
raise Error::TooShort.new(str, rule) unless str.split(//).length >= v
|
275
|
+
else
|
276
|
+
raise ArgumentError, "Invalid key: #{k}"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
return ret[:rule] || ret[:any] || ret[:all] || str
|
280
|
+
when Class then
|
281
|
+
begin
|
282
|
+
return rule.new(str)
|
283
|
+
rescue
|
284
|
+
raise Error::InvalidValue.new(str, rule)
|
285
|
+
end
|
286
|
+
when Symbol then
|
287
|
+
raise ArgumentError, "No such rule: #{rule}" unless @rule and @rule.key? rule
|
288
|
+
return self.class.validate(@rule[rule], str)
|
289
|
+
else
|
290
|
+
return rule if rule.to_s == str
|
291
|
+
end
|
292
|
+
raise Error::InvalidValue.new(str, rule)
|
293
|
+
end
|
294
|
+
|
295
|
+
# _rule_:: ルールキー。initialize に与えた Hash のキー
|
296
|
+
# _str_:: 対象文字列
|
297
|
+
#
|
298
|
+
# StringValidator#validate(_rule_, _str) が成功すれば true, そうでなければ false を返す。
|
299
|
+
#
|
300
|
+
def valid?(rule, str)
|
301
|
+
begin
|
302
|
+
validate(rule, str)
|
303
|
+
rescue Error
|
304
|
+
return false
|
305
|
+
end
|
306
|
+
return true
|
307
|
+
end
|
308
|
+
|
309
|
+
# _str_:: 対象文字列
|
310
|
+
#
|
311
|
+
# initialize に与えた Hash のキーのルールを順に評価し、最初に適合したキー値を返す。
|
312
|
+
# 適合したルールがない場合は nil を返す。
|
313
|
+
def validated_rule(str)
|
314
|
+
@rule.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |k|
|
315
|
+
if valid?(@rule[k], str) then
|
316
|
+
return k
|
317
|
+
end
|
318
|
+
end
|
319
|
+
return nil
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tmtm-stringvalidator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.4"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tomita Masahiro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-22 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: StringValidator is a Ruby library for validating string
|
17
|
+
email: tommy@tmtm.org
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/stringvalidator.rb
|
26
|
+
has_rdoc: true
|
27
|
+
homepage: http://github.com/tmtm/stringvalidator
|
28
|
+
licenses:
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options:
|
31
|
+
- --charset=utf-8
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: "0"
|
39
|
+
version:
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
requirements: []
|
47
|
+
|
48
|
+
rubyforge_project: stringvalidator
|
49
|
+
rubygems_version: 1.3.5
|
50
|
+
signing_key:
|
51
|
+
specification_version: 2
|
52
|
+
summary: StringValidator is a Ruby library for validating string
|
53
|
+
test_files: []
|
54
|
+
|