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

Types representing a single value, which are coerced through Virtus or special logic in Grape.

SPECIAL

Types for which Grape provides special coercion and type-checking logic.

STRUCTURES

Types representing data structures.

Public Class Methods

build_coercer(type, method = nil) click to toggle source

Work out the Virtus::Attribute object to use for coercing strings to the given type. Coercion method will be inferred if none is supplied.

If a Virtus::Attribute object already built with Virtus::Attribute.build is supplied as the type it will be returned and method will be ignored.

See {CustomTypeCoercer} for further details about coercion and type-checking inference.

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

should be coerced

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

for coercion and type validation
# File lib/grape/validations/types/build_coercer.rb, line 22
def self.build_coercer(type, method = nil)
  # Accept pre-rolled virtus attributes without interference
  return type if type.is_a? Virtus::Attribute

  converter_options = {
    nullify_blank: true
  }
  conversion_type = type

  # Use a special coercer for multiply-typed parameters.
  if Types.multiple?(type)
    converter_options[:coercer] = Types::MultipleTypeCoercer.new(type, method)
    conversion_type = Object

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

  # Grape swaps in its own Virtus::Attribute implementations
  # for certain special types that merit first-class support
  # (but not if a custom coercion method has been supplied).
  elsif Types.special?(type)
    conversion_type = Types::SPECIAL[type]
  end

  # Virtus will infer coercion and validation rules
  # for many common ruby types.
  Virtus::Attribute.build(conversion_type, converter_options)
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 149
def self.custom?(type)
  !primitive?(type) &&
    !structure?(type) &&
    !multiple?(type) &&
    !recognized?(type) &&
    !special?(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 141
def self.group?(type)
  GROUPS.include? 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 102
def self.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 78
def self.primitive?(type)
  PRIMITIVES.include?(type)
end
recognized?(type) click to toggle source

Does the given class implement a type system that Grape (i.e. the underlying virtus attribute system) supports out-of-the-box? Currently supported are axiom-types and virtus.

The type will be passed to Virtus::Attribute.build, and the resulting attribute object will be expected to respond correctly to coerce and value_coerced?.

@param type [Class] type to check @return [Boolean] true where the type is recognized

# File lib/grape/validations/types.rb, line 117
def self.recognized?(type)
  return false if type.is_a?(Array) || type.is_a?(Set)

  type.is_a?(Virtus::Attribute) ||
    type.ancestors.include?(Axiom::Types::Type) ||
    type.include?(Virtus::Model::Core)
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 132
def self.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

@note This method does not yet consider 'complex types', which inherit

Virtus.model.
# File lib/grape/validations/types.rb, line 90
def self.structure?(type)
  STRUCTURES.include?(type)
end