Module: Tap::Support::Validation
- Defined in:
- lib/tap/support/validation.rb
Overview
Validation generates blocks for common validations and transformations of configurations set through Configurable. In general these blocks load string inputs as YAML and valdiate the results; non-string inputs are simply validated.
integer = Validation.integer
integer.class # => Proc
integer.call(1) # => 1
integer.call('1') # => 1
integer.call(nil) # => ValidationError
– Note the unusual syntax for declaring constants that are blocks defined by lambda… ex:
block = lambda {}
CONST = block
This syntax plays well with RDoc, which otherwise gets jacked when you do it all in one step.
Defined Under Namespace
Classes: ValidationError, YamlizationError
Constant Summary collapse
- STRING =
string_validation_block
- STRING_OR_NIL =
string_or_nil_validation_block
- SYMBOL =
yamlize_and_check(Symbol)
- SYMBOL_OR_NIL =
yamlize_and_check(Symbol, nil)
- BOOLEAN =
yamlize_and_check(true, false, nil)
- SWITCH =
yamlize_and_check(true, false, nil)
- FLAG =
yamlize_and_check(true, false, nil)
- ARRAY =
yamlize_and_check(Array)
- ARRAY_OR_NIL =
yamlize_and_check(Array, nil)
- LIST =
list_block
- HASH =
yamlize_and_check(Hash)
- HASH_OR_NIL =
yamlize_and_check(Hash, nil)
- INTEGER =
yamlize_and_check(Integer)
- INTEGER_OR_NIL =
yamlize_and_check(Integer, nil)
- FLOAT =
yamlize_and_check(Float)
- FLOAT_OR_NIL =
yamlize_and_check(Float, nil)
- NUMERIC =
yamlize_and_check(Numeric)
- NUMERIC_OR_NIL =
yamlize_and_check(Numeric, nil)
- REGEXP =
regexp_block
- REGEXP_OR_NIL =
regexp_or_nil_block
- RANGE =
range_block
- RANGE_OR_NIL =
range_or_nil_block
- TIME =
time_block
- TIME_OR_NIL =
time_or_nil_block
Class Method Summary collapse
-
.array ⇒ Object
Returns a block that checks the input is an array.
-
.array_or_nil ⇒ Object
Same as array but allows nil:.
-
.boolean ⇒ Object
Returns a block that checks the input is true, false or nil.
-
.check(*validations) ⇒ Object
Returns a block that calls validate using the block input and the input validations.
-
.flag ⇒ Object
Same as boolean.
-
.float ⇒ Object
Returns a block that checks the input is a float.
-
.float_or_nil ⇒ Object
Same as float but allows nil:.
-
.hash ⇒ Object
Returns a block that checks the input is a hash.
-
.hash_or_nil ⇒ Object
Same as hash but allows nil:.
-
.integer ⇒ Object
Returns a block that checks the input is an integer.
-
.integer_or_nil ⇒ Object
Same as integer but allows nil:.
-
.list ⇒ Object
Returns a block that checks the input is an array.
-
.num ⇒ Object
Returns a block that checks the input is a number.
-
.num_or_nil ⇒ Object
Same as num but allows nil:.
-
.range ⇒ Object
Returns a block that checks the input is a range.
-
.range_or_nil ⇒ Object
Same as range but allows nil:.
-
.regexp ⇒ Object
Returns a block that checks the input is a regexp.
-
.regexp_or_nil ⇒ Object
Same as regexp but allows nil.
-
.string ⇒ Object
Returns a block that checks the input is a string.
-
.string_or_nil ⇒ Object
Same as string but allows nil.
-
.switch ⇒ Object
Same as boolean.
-
.symbol ⇒ Object
Returns a block that checks the input is a symbol.
-
.symbol_or_nil ⇒ Object
Same as symbol but allows nil:.
-
.time ⇒ Object
Returns a block that checks the input is a Time.
-
.time_or_nil ⇒ Object
Same as time but allows nil:.
-
.validate(input, validations) ⇒ Object
Returns input if any of the validations match any of the inputs, as in a case statement.
-
.yaml(*validations) ⇒ Object
Returns a block that loads input strings as YAML, then calls validate with the result and the input validations.
-
.yamlize(input) ⇒ Object
Attempts to load the input as YAML.
-
.yamlize_and_check(*validations) ⇒ Object
Returns a block loads a String input as YAML then validates the result is valid using the input validations.
Class Method Details
.array ⇒ Object
Returns a block that checks the input is an array. String inputs are loaded as yaml first.
array.class # => Proc
array.call([1,2,3]) # => [1,2,3]
array.call('[1, 2, 3]') # => [1,2,3]
array.call(nil) # => ValidationError
array.call('str') # => ValidationError
223 |
# File 'lib/tap/support/validation.rb', line 223 def array(); ARRAY; end |
.array_or_nil ⇒ Object
Same as array but allows nil:
array_or_nil.call('~') # => nil
array_or_nil.call(nil) # => nil
230 |
# File 'lib/tap/support/validation.rb', line 230 def array_or_nil(); ARRAY_OR_NIL; end |
.boolean ⇒ Object
Returns a block that checks the input is true, false or nil. String inputs are loaded as yaml first.
boolean.class # => Proc
boolean.call(true) # => true
boolean.call(false) # => false
boolean.call(nil) # => nil
boolean.call('true') # => true
boolean.call('yes') # => true
boolean.call('FALSE') # => false
boolean.call(1) # => ValidationError
boolean.call("str") # => ValidationError
203 |
# File 'lib/tap/support/validation.rb', line 203 def boolean(); BOOLEAN; end |
.check(*validations) ⇒ Object
Returns a block that calls validate using the block input and the input validations. Raises an error if no validations are specified.
96 97 98 99 |
# File 'lib/tap/support/validation.rb', line 96 def check(*validations) raise ArgumentError.new("no validations specified") if validations.empty? lambda {|input| validate(input, validations) } end |
.flag ⇒ Object
Same as boolean.
211 |
# File 'lib/tap/support/validation.rb', line 211 def flag(); FLAG; end |
.float ⇒ Object
Returns a block that checks the input is a float. String inputs are loaded as yaml first.
float.class # => Proc
float.call(1.1) # => 1.1
float.call('1.1') # => 1.1
float.call('1.0e+6') # => 1e6
float.call(1) # => ValidationError
float.call(nil) # => ValidationError
float.call('str') # => ValidationError
303 |
# File 'lib/tap/support/validation.rb', line 303 def float(); FLOAT; end |
.float_or_nil ⇒ Object
Same as float but allows nil:
float_or_nil.call('~') # => nil
float_or_nil.call(nil) # => nil
310 |
# File 'lib/tap/support/validation.rb', line 310 def float_or_nil(); FLOAT_OR_NIL; end |
.hash ⇒ Object
Returns a block that checks the input is a hash. String inputs are loaded as yaml first.
hash.class # => Proc
hash.call({'key' => 'value'}) # => {'key' => 'value'}
hash.call('key: value') # => {'key' => 'value'}
hash.call(nil) # => ValidationError
hash.call('str') # => ValidationError
262 |
# File 'lib/tap/support/validation.rb', line 262 def hash(); HASH; end |
.hash_or_nil ⇒ Object
Same as hash but allows nil:
hash_or_nil.call('~') # => nil
hash_or_nil.call(nil) # => nil
269 |
# File 'lib/tap/support/validation.rb', line 269 def hash_or_nil(); HASH_OR_NIL; end |
.integer ⇒ Object
Returns a block that checks the input is an integer. String inputs are loaded as yaml first.
integer.class # => Proc
integer.call(1) # => 1
integer.call('1') # => 1
integer.call(1.1) # => ValidationError
integer.call(nil) # => ValidationError
integer.call('str') # => ValidationError
282 |
# File 'lib/tap/support/validation.rb', line 282 def integer(); INTEGER; end |
.integer_or_nil ⇒ Object
Same as integer but allows nil:
integer_or_nil.call('~') # => nil
integer_or_nil.call(nil) # => nil
289 |
# File 'lib/tap/support/validation.rb', line 289 def integer_or_nil(); INTEGER_OR_NIL; end |
.list ⇒ Object
Returns a block that checks the input is an array. If the input is a string the string is split along commas and each value yamlized into an array.
list.class # => Proc
list.call([1,2,3]) # => [1,2,3]
list.call('1,2,3') # => [1,2,3]
list.call('str') # => ['str']
list.call(nil) # => ValidationError
243 |
# File 'lib/tap/support/validation.rb', line 243 def list(); LIST; end |
.num ⇒ Object
Returns a block that checks the input is a number. String inputs are loaded as yaml first.
num.class # => Proc
num.call(1.1) # => 1.1
num.call(1) # => 1
num.call(1e6) # => 1e6
num.call('1.1') # => 1.1
num.call('1.0e+6') # => 1e6
num.call(nil) # => ValidationError
num.call('str') # => ValidationError
325 |
# File 'lib/tap/support/validation.rb', line 325 def num(); NUMERIC; end |
.num_or_nil ⇒ Object
Same as num but allows nil:
num_or_nil.call('~') # => nil
num_or_nil.call(nil) # => nil
332 |
# File 'lib/tap/support/validation.rb', line 332 def num_or_nil(); NUMERIC_OR_NIL; end |
.range ⇒ Object
Returns a block that checks the input is a range. String inputs are split into a beginning and end if possible, where each part is loaded as yaml before being used to construct a Range.a
range.class # => Proc
range.call(1..10) # => 1..10
range.call('1..10') # => 1..10
range.call('a..z') # => 'a'..'z'
range.call('-10...10') # => -10...10
range.call(nil) # => ValidationError
range.call('1.10') # => ValidationError
range.call('a....z') # => ValidationError
388 |
# File 'lib/tap/support/validation.rb', line 388 def range(); RANGE; end |
.range_or_nil ⇒ Object
Same as range but allows nil:
range_or_nil.call('~') # => nil
range_or_nil.call(nil) # => nil
401 |
# File 'lib/tap/support/validation.rb', line 401 def range_or_nil(); RANGE_OR_NIL; end |
.regexp ⇒ Object
Returns a block that checks the input is a regexp. String inputs are converted to regexps using Regexp#new.
regexp.class # => Proc
regexp.call(/regexp/) # => /regexp/
regexp.call('regexp') # => /regexp/
# use of ruby-specific flags can turn on/off
# features like case insensitive matching
regexp.call('(?i)regexp') # => /(?i)regexp/
347 |
# File 'lib/tap/support/validation.rb', line 347 def regexp(); REGEXP; end |
.regexp_or_nil ⇒ Object
Same as regexp but allows nil. Note the special behavior of the nil string ‘~’ – rather than being converted to a regexp, it is processed as nil to be consistent with the other [class]_or_nil methods.
regexp_or_nil.call('~') # => nil
regexp_or_nil.call(nil) # => nil
362 |
# File 'lib/tap/support/validation.rb', line 362 def regexp_or_nil(); REGEXP_OR_NIL; end |
.string ⇒ Object
Returns a block that checks the input is a string. Moreover, strings are re-evaluated as string literals using %Q.
string.class # => Proc
string.call('str') # => 'str'
string.call('\n') # => "\n"
string.call("\n") # => "\n"
string.call("%s") # => "%s"
string.call(nil) # => ValidationError
string.call(:sym) # => ValidationError
144 |
# File 'lib/tap/support/validation.rb', line 144 def string(); STRING; end |
.string_or_nil ⇒ Object
Same as string but allows nil. Note the special behavior of the nil string ‘~’ – rather than being treated as a string, it is processed as nil to be consistent with the other [class]_or_nil methods.
string_or_nil.call('~') # => nil
string_or_nil.call(nil) # => nil
159 |
# File 'lib/tap/support/validation.rb', line 159 def string_or_nil(); STRING_OR_NIL; end |
.switch ⇒ Object
Same as boolean.
207 |
# File 'lib/tap/support/validation.rb', line 207 def switch(); SWITCH; end |
.symbol ⇒ Object
Returns a block that checks the input is a symbol. String inputs are loaded as yaml first.
symbol.class # => Proc
symbol.call(:sym) # => :sym
symbol.call(':sym') # => :sym
symbol.call(nil) # => ValidationError
symbol.call('str') # => ValidationError
178 |
# File 'lib/tap/support/validation.rb', line 178 def symbol(); SYMBOL; end |
.symbol_or_nil ⇒ Object
Same as symbol but allows nil:
symbol_or_nil.call('~') # => nil
symbol_or_nil.call(nil) # => nil
185 |
# File 'lib/tap/support/validation.rb', line 185 def symbol_or_nil(); SYMBOL_OR_NIL; end |
.time ⇒ Object
Returns a block that checks the input is a Time. String inputs are loaded using Time.parse and then converted into times. Parsed times are local unless specified otherwise.
time.class # => Proc
now = Time.now
time.call(now) # => now
time.call('2008-08-08 20:00:00.00 +08:00').getutc.strftime('%Y/%m/%d %H:%M:%S')
# => '2008/08/08 12:00:00'
time.call('2008-08-08').strftime('%Y/%m/%d %H:%M:%S')
# => '2008/08/08 00:00:00'
time.call(1) # => ValidationError
time.call(nil) # => ValidationError
Warning: Time.parse will parse a valid time (Time.now) even when no time is specified:
time.call('str').strftime('%Y/%m/%d %H:%M:%S')
# => Time.now.strftime('%Y/%m/%d %H:%M:%S')
442 443 444 445 446 447 |
# File 'lib/tap/support/validation.rb', line 442 def time() # adding this here is a compromise to lazy-load the parse # method (autoload doesn't work since Time already exists) require 'time' unless Time.respond_to?(:parse) TIME end |
.time_or_nil ⇒ Object
Same as time but allows nil:
time_or_nil.call('~') # => nil
time_or_nil.call(nil) # => nil
459 460 461 462 463 464 |
# File 'lib/tap/support/validation.rb', line 459 def time_or_nil() # adding this check is a compromise to autoload the parse # method (autoload doesn't work since Time already exists) require 'time' unless Time.respond_to?(:parse) TIME_OR_NIL end |
.validate(input, validations) ⇒ Object
Returns input if any of the validations match any of the inputs, as in a case statement. Raises a ValidationError otherwise. For example:
validate(10, [Integer, nil])
Does the same as:
case 10
when Integer, nil then input
else raise ValidationError.new(...)
end
Note the validations input must be an Array or nil; validate will raise an ArgumentError otherwise.
All inputs are considered VALID if validations == nil.
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/tap/support/validation.rb', line 69 def validate(input, validations) case validations when Array case input when *validations then input else raise ValidationError.new(input, validations) end when nil then input else raise ArgumentError.new("validations must be nil, or an array of valid inputs") end end |
.yaml(*validations) ⇒ Object
Returns a block that loads input strings as YAML, then calls validate with the result and the input validations. Non-string inputs are not converted.
b = yaml(Integer, nil)
b.class # => Proc
b.call(1) # => 1
b.call("1") # => 1
b.call(nil) # => nil
b.call("str") # => ValidationError
If no validations are specified, the result will be returned without validation.
114 115 116 117 118 119 |
# File 'lib/tap/support/validation.rb', line 114 def yaml(*validations) lambda do |input| res = input.kind_of?(String) ? yamlize(input) : input validations.empty? ? res : validate(res, validations) end end |
.yamlize(input) ⇒ Object
Attempts to load the input as YAML. Raises a YamlizationError for errors.
85 86 87 88 89 90 91 |
# File 'lib/tap/support/validation.rb', line 85 def yamlize(input) begin YAML.load(input) rescue raise YamlizationError.new(input, $!.) end end |
.yamlize_and_check(*validations) ⇒ Object
Returns a block loads a String input as YAML then validates the result is valid using the input validations. If the input is not a String, the input is validated directly.
125 126 127 128 129 130 |
# File 'lib/tap/support/validation.rb', line 125 def yamlize_and_check(*validations) lambda do |input| input = yamlize(input) if input.kind_of?(String) validate(input, validations) end end |