class Mixture::Types::Type
A single type. A type is never instantized; it is used as a class to represent a type of value.
Public Class Methods
If this class is anonymous. This is counting on the fact that the name of an anonymous class is nil; however, assigning a class to a constant on initialization of a class will make that class non-anonymous.
@return [Boolean]
# File lib/mixture/types/type.rb, line 92 def self.anonymous? name.nil? end
Sets some names that this type can go under. This is used for {Type.mappings} and for inference.
@see Types.mappings
@see .mappings @param names [Symbol, Object] @return [void]
# File lib/mixture/types/type.rb, line 43 def self.as(*names) mappings.concat(names) end
This is used to determine if a specific object is this type. There can be many constraints, and they're all used to check the given object.
@note Constraints are not meant for validation. Constraints
are **purely** meant for identification, and should be used as such.
@overload self.constraint(value)
Adds the value as a constraint. Ideally, this should respond to `#call`. @example Subclass constraint. constraint(->(value) { value.is_a?(String) }) @param value [#call] The constraint to add. @return [void]
@overload self.constraint(&block)
Adds the block as a constraint. @example Subclass constraint. constraint { |value| value.is_a?(String) } @yield [value] @yieldparam value [Object] The value to check. @yieldreturn [Boolean] If the constraint was passed. @return [void]
# File lib/mixture/types/type.rb, line 140 def self.constraint(value = Undefined, &block) if block_given? constraints << block elsif value != Undefined constraints << value else fail ArgumentError, "Expected an argument or a block, " \ "got neither" end end
Constraints on the type. A value will not match the type if any of these constraints fail. This is inherited by subtypes.
@return [Array<Proc{(Object
) => Boolean}>]
# File lib/mixture/types/type.rb, line 23 def self.constraints @constraints ||= ThreadSafe::Array.new end
A list of types that this type can inherit coercion behavior from. For example, a collection can be coerced into an array or a set.
@return [Array<Class>]
# File lib/mixture/types/type.rb, line 82 def self.inheritable ancestors - Type.ancestors end
Called by ruby when a class inherits this class. This just propogates the options and constraints to the new subclass.
@param sub [Class] The new subclass. @return [void]
# File lib/mixture/types/type.rb, line 52 def self.inherited(sub) sub.options.merge!(options) sub.constraints.concat(constraints) end
Inspects the class. If the class is anonymous, it uses the `:name` value in the options if it exists. Otherwise, it passes it up the chain.
@return [String]
# File lib/mixture/types/type.rb, line 101 def self.inspect to_s end
Returns all of the names that this type can go under. This is used for {Types.mappings} and for inference.
@see Types.mappings
@return [Array<Symbol, Object>]
# File lib/mixture/types/type.rb, line 32 def self.mappings @mappings ||= ThreadSafe::Array.new end
Checks if the given value passes all of the constraints defined on this type. Each constraint is executed within the context of the class, to provide access to {.options}.
@param value [Object] The object to check. @return [Boolean]
# File lib/mixture/types/type.rb, line 71 def self.matches?(value) constraints.all? do |constraint| class_exec(value, &constraint) end end
The options for the type. This is inherited by subtypes.
@return [Hash{Symbol => Object}]
# File lib/mixture/types/type.rb, line 15 def self.options @options ||= ThreadSafe::Hash.new end
Registers the type. This shouldn't be called on anonymous classes.
@return [void]
# File lib/mixture/types/type.rb, line 61 def self.register Types.types << self end
(see .inspect)
# File lib/mixture/types/type.rb, line 106 def self.to_s if anonymous? && options.key?(:name) options[:name] else super end end