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
Public Class Methods
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
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
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
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
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
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
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