class Toys::Settings::Type

A type object that checks values.

A Type includes a description string and a testing function. The testing function takes a proposed value and returns either the value itself if it is valid, a converted value if the value can be converted to a valid value, or {ILLEGAL_VALUE} if the type check failed.

Constants

CONVERTERS

@private

Attributes

description[R]

The name of the type. @return [String]

Public Class Methods

for_default_value(value) click to toggle source

Create and return a Type given a default value. See the {Settings} class documentation for the rules.

@param value [Object] @return [Type]

# File lib/toys/settings.rb, line 427
def for_default_value(value)
  case value
  when nil
    for_module(::Object)
  when true, false
    for_union([true, false])
  else
    for_module(value.class)
  end
end
for_type_spec(type_spec) click to toggle source

Create and return a Type given a type specification. See the {Settings} class documentation for valid type specifications.

@param type_spec [Object] @return [Type] @raise [ArgumentError] if the type specification is invalid.

# File lib/toys/settings.rb, line 399
def for_type_spec(type_spec)
  case type_spec
  when Type
    type_spec
  when ::Module
    for_module(type_spec)
  when ::Range
    for_range(type_spec)
  when ::Regexp
    for_regexp(type_spec)
  when ::Array
    for_union(type_spec)
  when ::Proc
    new("(opaque proc)", &type_spec)
  when nil, true, false, ::String, ::Symbol, ::Numeric
    for_scalar(type_spec)
  else
    raise ::ArgumentError, "Illegal type spec: #{type_spec.inspect}"
  end
end
new(description, &block) click to toggle source

Create a new Type.

@param description [String] Name of the type. @param block [Proc] A testing function.

# File lib/toys/settings.rb, line 368
def initialize(description, &block)
  @description = description.freeze
  @tester = block
end

Private Class Methods

convert(val, klass) click to toggle source
# File lib/toys/settings.rb, line 486
def convert(val, klass)
  return val if val.is_a?(klass)
  begin
    CONVERTERS[klass].call(val)
  rescue ::StandardError
    ILLEGAL_VALUE
  end
end
for_module(klass) click to toggle source
# File lib/toys/settings.rb, line 440
def for_module(klass)
  new(klass.to_s) do |val|
    convert(val, klass)
  end
end
for_range(range) click to toggle source
# File lib/toys/settings.rb, line 446
def for_range(range)
  range_class = (range.begin || range.end).class
  new("(#{range})") do |val|
    converted = convert(val, range_class)
    range.member?(converted) ? converted : ILLEGAL_VALUE
  end
end
for_regexp(regexp) click to toggle source
# File lib/toys/settings.rb, line 454
def for_regexp(regexp)
  regexp_str = regexp.source.gsub("/", "\\/")
  new("/#{regexp_str}/") do |val|
    str = val.to_s
    regexp.match(str) ? str : ILLEGAL_VALUE
  end
end
for_scalar(value) click to toggle source
# File lib/toys/settings.rb, line 480
def for_scalar(value)
  new(value.inspect) do |val|
    val == value ? val : ILLEGAL_VALUE
  end
end
for_union(array) click to toggle source
# File lib/toys/settings.rb, line 462
def for_union(array)
  types = array.map { |elem| for_type_spec(elem) }
  descriptions = types.map(&:description).join(", ")
  new("[#{descriptions}]") do |val|
    result = ILLEGAL_VALUE
    types.each do |type|
      converted = type.call(val)
      if converted == val
        result = val
        break
      elsif result == ILLEGAL_VALUE
        result = converted
      end
    end
    result
  end
end

Public Instance Methods

call(val) click to toggle source

Test a value, possibly converting to a legal value.

@param val [Object] The value to be tested. @return [Object] The validated value, the value converted to a legal

value, or {ILLEGAL_VALUE} if the type check is unsuccessful.
# File lib/toys/settings.rb, line 386
def call(val)
  @tester.call(val)
end