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
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/build_coercer.rb, line 38 def self.build_coercer(type, method: nil, strict: false) cache_instance(type, method, strict) do create_coercer_instance(type, method, strict) end end
# File lib/grape/validations/types/build_coercer.rb, line 68 def self.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
# File lib/grape/validations/types/build_coercer.rb, line 82 def self.cache_key(type, method, strict) [type, method, strict].each_with_object(+'_') do |val, memo| next if val.nil? memo << '_' << val.to_s end end
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 137 def self.collection_of_custom?(type) (type.is_a?(Array) || type.is_a?(Set)) && type.length == 1 && (custom?(type.first) || special?(type.first)) end
# File lib/grape/validations/types/build_coercer.rb, line 44 def self.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
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 124 def self.custom?(type) !primitive?(type) && !structure?(type) && !multiple?(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 115 def self.group?(type) GROUPS.include? type end
# File lib/grape/validations/types.rb, line 143 def self.map_special(type) SPECIAL.fetch(type, 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 95 def self.multiple?(type) (type.is_a?(Array) || type.is_a?(Set)) && type.size > 1 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 106 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
# File lib/grape/validations/types.rb, line 83 def self.structure?(type) STRUCTURES.include?(type) end