module Grape::Validations::Types

Module for code related to grape’s system for coercion and type validation of incoming request parameters.

Grape uses a number of tests and assertions to work out exactly how a parameter should be handled, based on the type and coerce_with options that may be supplied to {Grape::Dsl::Parameters#requires} and {Grape::Dsl::Parameters#optional}. The main entry point for this process is {Types.build_coercer}.

Constants

GROUPS
PRIMITIVES
SPECIAL
STRUCTURES

Types representing data structures.

Public Instance Methods

build_coercer(type, method: nil, strict: false) click to toggle source

Chooses the best coercer for the given type. For example, if the type is Integer, it will return a coercer which will be able to coerce a value to the integer.

There are a few very special coercers which might be returned.

Grape::Types::MultipleTypeCoercer is a coercer which is returned when the given type implies values in an array with different types. For example, +[Integer, String]+ allows integer and string values in an array.

Grape::Types::CustomTypeCoercer is a coercer which is returned when a method is specified by a user with coerce_with option or the user specifies a custom type which implements requirments of Grape::Types::CustomTypeCoercer.

Grape::Types::CustomTypeCollectionCoercer is a very similar to the previous one, but it expects an array or set of values having a custom type implemented by the user.

There is also a group of custom types implemented by Grape, check Grape::Validations::Types::SPECIAL to get the full list.

@param type [Class] the type to which input strings

should be coerced

@param method [Class,#call] the coercion method to use @return [Object] object to be used

for coercion and type validation
# File lib/grape/validations/types.rb, line 157
def build_coercer(type, method: nil, strict: false)
  cache_instance(type, method, strict) do
    create_coercer_instance(type, method, strict)
  end
end
cache_instance(type, method, strict) { || ... } click to toggle source
# File lib/grape/validations/types.rb, line 187
def cache_instance(type, method, strict, &_block)
  key = cache_key(type, method, strict)

  return @__cache[key] if @__cache.key?(key)

  instance = yield

  @__cache_write_lock.synchronize do
    @__cache[key] = instance
  end

  instance
end
cache_key(type, method, strict) click to toggle source
# File lib/grape/validations/types.rb, line 201
def cache_key(type, method, strict)
  [type, method, strict].each_with_object(+'_') do |val, memo|
    next if val.nil?

    memo << '_' << val.to_s
  end
end
collection_of_custom?(type) click to toggle source

Is the declared type an Array or Set of a {#custom?} type?

@param type [Array<Class>,Class] type to check @return [Boolean] true if type is a collection of a type that implements

its own +#parse+ method.
# File lib/grape/validations/types.rb, line 119
def collection_of_custom?(type)
  (type.is_a?(Array) || type.is_a?(Set)) &&
    type.length == 1 &&
    (custom?(type.first) || special?(type.first))
end
create_coercer_instance(type, method, strict) click to toggle source
# File lib/grape/validations/types.rb, line 163
def create_coercer_instance(type, method, strict)
  # Maps a custom type provided by Grape, it doesn't map types wrapped by collections!!!
  type = Types.map_special(type)

  # Use a special coercer for multiply-typed parameters.
  if Types.multiple?(type)
    MultipleTypeCoercer.new(type, method)

    # Use a special coercer for custom types and coercion methods.
  elsif method || Types.custom?(type)
    CustomTypeCoercer.new(type, method)

    # Special coercer for collections of types that implement a parse method.
    # CustomTypeCoercer (above) already handles such types when an explicit coercion
    # method is supplied.
  elsif Types.collection_of_custom?(type)
    Types::CustomTypeCollectionCoercer.new(
      Types.map_special(type.first), type.is_a?(Set)
    )
  else
    DryTypeCoercer.coercer_instance_for(type, strict)
  end
end
custom?(type) click to toggle source

A valid custom type must implement a class-level ‘parse` method, taking one String argument and returning the parsed value in its correct type.

@param type [Class] type to check @return [Boolean] whether or not the type can be used as a custom type

# File lib/grape/validations/types.rb, line 106
def custom?(type)
  !primitive?(type) &&
    !structure?(type) &&
    !multiple?(type) &&
    type.respond_to?(:parse) &&
    type.method(:parse).arity == 1
end
group?(type) click to toggle source

Is the declared type a supported group type? Currently supported group types are Array, Hash, JSON, and Array

@param type [Array<Class>,Class] type to check @return [Boolean] true if the type is a supported group type

# File lib/grape/validations/types.rb, line 97
def group?(type)
  GROUPS.include? type
end
map_special(type) click to toggle source
# File lib/grape/validations/types.rb, line 125
def map_special(type)
  SPECIAL.fetch(type, type)
end
multiple?(type) click to toggle source

Is the declared type in fact an array of multiple allowed types? For example the declaration +types: [Integer,String]+ will attempt first to coerce given values to integer, but will also accept any other string.

@param type [Array<Class>,Set<Class>] type (or type list!) to check @return [Boolean] true if the given value will be treated as

a list of types.
# File lib/grape/validations/types.rb, line 77
def multiple?(type)
  (type.is_a?(Array) || type.is_a?(Set)) && type.size > 1
end
primitive?(type) click to toggle source

Is the given class a primitive type as recognized by Grape?

@param type [Class] type to check @return [Boolean] whether or not the type is known by Grape as a valid

type for a single value
# File lib/grape/validations/types.rb, line 55
def primitive?(type)
  PRIMITIVES.include?(type)
end
special?(type) click to toggle source

Does Grape provide special coercion and validation routines for the given class? This does not include automatic handling for primitives, structures and otherwise recognized types. See {Types::SPECIAL}.

@param type [Class] type to check @return [Boolean] true if special routines are available

# File lib/grape/validations/types.rb, line 88
def special?(type)
  SPECIAL.key? type
end
structure?(type) click to toggle source

Is the given class a standard data structure (collection or map) as recognized by Grape?

@param type [Class] type to check @return [Boolean] whether or not the type is known by Grape as a valid

data structure type
# File lib/grape/validations/types.rb, line 65
def structure?(type)
  STRUCTURES.include?(type)
end