lib/configurable/validation.rb in configurable-0.5.0 vs lib/configurable/validation.rb in configurable-0.6.0

- old
+ new

@@ -6,11 +6,11 @@ DEFAULT_ATTRIBUTES = Hash.new({}) DEFAULT_ATTRIBUTES[nil] = {:reader => true, :writer => true} # 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 + # string inputs as YAML and validate the results; non-string inputs are # simply validated. # # integer = Validation.integer # integer.class # => Proc # integer.call(1) # => 1 @@ -54,11 +54,11 @@ module_function # Registers the default attributes with the specified block # in Configurable::DEFAULT_ATTRIBUTES. - def register(block, attributes) + def register(attributes={}, &block) DEFAULT_ATTRIBUTES[block] = attributes block end # Registers the default attributes of the source as the attributes @@ -205,11 +205,11 @@ eval %Q{"#{input}"} end # default attributes {:type => :string, :example => "string"} STRING = string_validation_block - register STRING, :type => :string, :example => "string" + register :type => :string, :example => "string", &STRING # 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 @@ -240,21 +240,61 @@ # def symbol(); SYMBOL; end # default attributes {:type => :symbol, :example => ":sym"} SYMBOL = yaml(Symbol) - register SYMBOL, :type => :symbol, :example => ":sym" + register :type => :symbol, :example => ":sym", &SYMBOL # Same as symbol but allows nil: # # symbol_or_nil.call('~') # => nil # symbol_or_nil.call(nil) # => nil def symbol_or_nil(); SYMBOL_OR_NIL; end SYMBOL_OR_NIL = yaml(Symbol, nil) register_as SYMBOL, SYMBOL_OR_NIL + # Returns a block that checks the input is a symbol. + # String inputs are directly converted to a symbol. + # + # strbol.class # => Proc + # strbol.call(:sym) # => :sym + # strbol.call(':sym') # => :":sym" + # strbol.call('str') # => :sym + # strbol.call(nil) # => ValidationError + # + def strbol(); STRBOL; end + + # default attributes {:type => :symbol, :example => ":sym"} + STRBOL = lambda do |input| + if input.kind_of?(String) + input = input.to_sym + end + + validate(input, [Symbol]) + end + register :type => :symbol, :example => ":sym", &STRBOL + + # Same as strbol but allows nil. Tilde is considered a string + # equivalent of nil (this behavior is consistent with the YAML + # methods but obviously inconsistent with the strbol behavior). + # + # strbol_or_nil.call('~') # => nil + # strbol_or_nil.call(nil) # => nil + def strbol_or_nil(); STRBOL_OR_NIL; end + + STRBOL_OR_NIL = lambda do |input| + input = case input + when "~" then nil + when String then input.to_sym + else input + end + + validate(input, [Symbol, nil]) + end + register_as STRBOL, STRBOL_OR_NIL + # 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 @@ -270,25 +310,25 @@ # def boolean(); BOOLEAN; end # default attributes {:type => :boolean, :example => "true, yes"} BOOLEAN = yaml(true, false, nil) - register BOOLEAN, :type => :boolean, :example => "true, yes" + register :type => :boolean, :example => "true, yes", &BOOLEAN # Same as boolean. def switch(); SWITCH; end # default attributes {:type => :switch} SWITCH = yaml(true, false, nil) - register SWITCH, :type => :switch + register :type => :switch, &SWITCH # Same as boolean. def flag(); FLAG; end # default attributes {:type => :flag} FLAG = yaml(true, false, nil) - register FLAG, :type => :flag + register :type => :flag, &FLAG # Returns a block that checks the input is an array. # String inputs are loaded as yaml first. # # array.class # => Proc @@ -299,11 +339,11 @@ # def array(); ARRAY; end # default attributes {:type => :array, :example => "[a, b, c]"} ARRAY = yaml(Array) - register ARRAY, :type => :array, :example => "[a, b, c]" + register :type => :array, :example => "[a, b, c]", &ARRAY # Same as array but allows nil: # # array_or_nil.call('~') # => nil # array_or_nil.call(nil) # => nil @@ -341,11 +381,11 @@ end end # default attributes {:type => :list, :split => ','} LIST = list_block - register LIST, :type => :list, :split => ',' + register :type => :list, :split => ',', &LIST # Returns a block that checks the input is a hash. # String inputs are loaded as yaml first. # # hash.class # => Proc @@ -356,11 +396,11 @@ # def hash(); HASH; end # default attributes {:type => :hash, :example => "{one: 1, two: 2}"} HASH = yaml(Hash) - register HASH, :type => :hash, :example => "{one: 1, two: 2}" + register :type => :hash, :example => "{one: 1, two: 2}", &HASH # Same as hash but allows nil: # # hash_or_nil.call('~') # => nil # hash_or_nil.call(nil) # => nil @@ -381,11 +421,11 @@ # def integer(); INTEGER; end # default attributes {:type => :integer, :example => "2"} INTEGER = yaml(Integer) - register INTEGER, :type => :integer, :example => "2" + register :type => :integer, :example => "2", &INTEGER # Same as integer but allows nil: # # integer_or_nil.call('~') # => nil # integer_or_nil.call(nil) # => nil @@ -407,11 +447,11 @@ # def float(); FLOAT; end # default attributes {:type => :float, :example => "2.2, 2.0e+2"} FLOAT = yaml(Float) - register FLOAT, :type => :float, :example => "2.2, 2.0e+2" + register :type => :float, :example => "2.2, 2.0e+2", &FLOAT # Same as float but allows nil: # # float_or_nil.call('~') # => nil # float_or_nil.call(nil) # => nil @@ -434,11 +474,11 @@ # def numeric(); NUMERIC; end # default attributes {:type => :numeric, :example => "2, 2.2, 2.0e+2"} NUMERIC = yaml(Numeric) - register NUMERIC, :type => :numeric, :example => "2, 2.2, 2.0e+2" + register :type => :numeric, :example => "2, 2.2, 2.0e+2", &NUMERIC # Same as numeric but allows nil: # # numeric_or_nil.call('~') # => nil # numeric_or_nil.call(nil) # => nil @@ -475,11 +515,11 @@ validate(input, [Regexp]) end # default attributes {:type => :regexp, :example => "/regexp/i"} REGEXP = regexp_block - register REGEXP, :type => :regexp, :example => "/regexp/i" + register :type => :regexp, :example => "/regexp/i", &REGEXP # 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. # @@ -522,11 +562,11 @@ validate(input, [Range]) end # default attributes {:type => :range, :example => "min..max"} RANGE = range_block - register RANGE, :type => :range, :example => "min..max" + register :type => :range, :example => "min..max", &RANGE # Same as range but allows nil: # # range_or_nil.call('~') # => nil # range_or_nil.call(nil) # => nil @@ -577,11 +617,11 @@ validate(input, [Time]) end # default attributes {:type => :time, :example => "2008-08-08 08:00:00"} TIME = time_block - register TIME, :type => :time, :example => "2008-08-08 08:00:00" + register :type => :time, :example => "2008-08-08 08:00:00", &TIME # Same as time but allows nil: # # time_or_nil.call('~') # => nil # time_or_nil.call(nil) # => nil @@ -612,19 +652,18 @@ # The select block is registered with these default attributes: # # {:type => :select, :options => options} # def select(*options, &validation) - block = lambda do |input| + register( + :type => :select, + :options => options, + :validation => attributes(validation) + ) do |input| input = validation.call(input) if validation validate(input, options) end - - register(block, - :type => :select, - :options => options, - :validation => attributes(validation)) end # Returns a block that checks the input is an array, and that each member # of the array is included in options. A block may be provided to validate # the individual values. @@ -643,21 +682,20 @@ # The list_select block is registered with these default attributes: # # {:type => :list_select, :options => options, :split => ','} # def list_select(*options, &validation) - block = lambda do |input| + register( + :type => :list_select, + :options => options, + :split => ',', + :validation => attributes(validation) + ) do |input| args = validate(input, [Array]) args.collect! {|arg| validation.call(arg) } if validation args.each {|arg| validate(arg, options) } end - - register(block, - :type => :list_select, - :options => options, - :split => ',', - :validation => attributes(validation)) end # Returns a block validating the input is an IO, a string, or an integer. # String inputs are expected to be filepaths and integer inputs are expected # to be valid file descriptors, but io does not open an IO immediately. @@ -691,12 +729,12 @@ register_as IO_OR_STRING, block end end - # default attributes {:type => :io, :duplicate_default => false, :example => "/path/to/file"} + # default attributes {:type => :io, :dup => false, :example => "/path/to/file"} IO_OR_STRING = check(IO, String, Integer) - register IO_OR_STRING, :type => :io, :duplicate_default => false, :example => "/path/to/file" + register :type => :io, :dup => false, :example => "/path/to/file", &IO_OR_STRING # Same as io but allows nil: # # io_or_nil.call(nil) # => nil # \ No newline at end of file