class Grape::Validations::Types::CustomTypeCoercer

method.
contract as coerced?, and must be supplied with a coercion
supplied in place of a type. This should implement the same
Alternately a proc or other object responding to call may be
system should be preferred.
Arbitrary assertions may be made here but the grape validation
and should return true if the value meets type expectations.
will receive a single parameter that is the coerced value
coerced? or parsed? method. This method
overridden if the class implements a class-level
against the type supplied, but this behaviour will be
expected type. By default this class performs a basic check
that the coerced value produced above is in fact of the
Calls to coerced? will consult this class to check
————-
Type Checking
with the same contract as described above.
This may be any class or object implementing parse or call,
coerce_with option of {Grape::Dsl::Parameters#requires}).
Alternately an optional method may be supplied (see the
there are any problems parsing the string.
the appropriate type. The method may raise an exception if
String argument and should return the value coerced to
a class-level parse method. The method should accept one
This class will detect type classes that implement

def call(val)

Returns:
  • (Object) - the coerced result

Parameters:
  • value (String) -- value to be coerced, in grape
def call(val)
  coerced_val = @method.call(val)
  return coerced_val if coerced_val.is_a?(InvalidValue)
  return InvalidValue.new unless coerced?(coerced_val)
  coerced_val
end

def coerced?(val)

def coerced?(val)
  val.nil? || @type_check.call(val)
end

def enforce_symbolized_keys(type, method)

Returns:
  • (#call) - +method+ wrapped in an additional

Parameters:
  • method () -- see #infer_coercion_method
  • type () -- see #new
def enforce_symbolized_keys(type, method)
  # Collections have all values processed individually
  if [Array, Set].include?(type)
    lambda do |val|
      method.call(val).tap do |new_val|
        new_val.map do |item|
          item.is_a?(Hash) ? item.deep_symbolize_keys : item
        end
      end
    end
  # Hash objects are processed directly
  elsif type == Hash
    lambda do |val|
      method.call(val).deep_symbolize_keys
    end
  # Simple types are not processed.
  # This includes Array<primitive> types.
  else
    method
  end
end

def infer_coercion_method(type, method)

Returns:
  • (#call) - coercion method

Parameters:
  • method () -- see #new
  • type () -- see #new
def infer_coercion_method(type, method)
  if method
    if method.respond_to? :parse
      method.method :parse
    else
      method
    end
  else
    # Try to use parse() declared on the target type.
    # This may raise an exception, but we are out of ideas anyway.
    type.method :parse
  end
end

def infer_type_check(type)

Returns:
  • (#call) - a procedure which accepts a single parameter

Parameters:
  • type () -- see #new
def infer_type_check(type)
  # First check for special class methods
  if type.respond_to? :coerced?
    type.method :coerced?
  elsif type.respond_to? :parsed?
    type.method :parsed?
  elsif type.respond_to? :call
    # Arbitrary proc passed for type validation.
    # Note that this will fail unless a method is also
    # passed, or if the type also implements a parse() method.
    type
  elsif type.is_a?(Enumerable)
    lambda do |value|
      value.is_a?(Enumerable) && value.all? do |val|
        recursive_type_check(type.first, val)
      end
    end
  else
    # By default, do a simple type check
    ->(value) { value.is_a? type }
  end
end

def initialize(type, method = nil)

Parameters:
  • method (#parse, #call) --
  • type (Class, #coerced?, #parsed?, #call?) --
def initialize(type, method = nil)
  coercion_method = infer_coercion_method type, method
  @method = enforce_symbolized_keys type, coercion_method
  @type_check = infer_type_check(type)
end

def recursive_type_check(type, value)

def recursive_type_check(type, value)
  if type.is_a?(Enumerable) && value.is_a?(Enumerable)
    value.all? { |val| recursive_type_check(type.first, val) }
  else
    !type.is_a?(Enumerable) && value.is_a?(type)
  end
end