class Mixture::Coerce::Base

The base for coercion actions. Each action defines the “from” type, and the instance handles the “to”.

Public Class Methods

coerce_to(to, data = Undefined, &block) click to toggle source

This is a DSL for the class itself. It essentially defines a method to perform the coercion of the given type.

@overload coerce_to(to) { }

This is a DSL for the class itself.  It essentially defines
a method to perform the coercion of the given type.

@param to [Mixture::Types::Type] The type to coerce to.
@yield [value, type] The block is called with the value to
  coerce when coercion needs to happen.  Note that the
  block is not used as the body of the method - the method
  returns the block.
@yieldparam value [Object] The object to coerce.
@yieldparam type [Mixture::Types::Type] The destination type.
@yieldreturn [Object] The coerced value.
@return [void]

@overload coerce_to(to, value)

This is a DSL for the class itself.  It essentially defines
a method to perform the coercion of the given type.

@param to [Mixture::Types::Type] The type to coerce to.
@param value [Proc, Symbol] The block that is called with
  the value for coercion.  This block is returned by
  the defined coercion method.  If it's a symbol, it's
  turned into a block.  Note that this doesn't use
  Symbol#to_proc; it uses a similar block that ignores
  the excess paramters.
@return [void]
# File lib/mixture/coerce/base.rb, line 86
def self.coerce_to(to, data = Undefined, &block)
  fail ArgumentError, "Expected Mixture::Types::Type, got #{to}" unless
    to <= Mixture::Types::Type

  body = data_block(data, &block)
  coercions[to] = to.options[:method]
  define_method(to.options[:method]) { body }
end
coercions() click to toggle source

The coercions that this class has. It's a map of the type to the method that performs that coercion.

@return [Hash{Mixture::Type => Symbol}]

# File lib/mixture/coerce/base.rb, line 34
def self.coercions
  @_coercions ||= ThreadSafe::Hash.new
end
data_block(data, &block) click to toggle source

Turns a data/block given to {.coerce_to} into a block worthy of a body for a method.

@param data [Proc, Symbol] A proc/symbol to be used for a

method.

@yield (see .coerce_to) @yieldparam (see .coerce_to) @yieldreturn (see .coerce_to) @return [void]

# File lib/mixture/coerce/base.rb, line 104
def self.data_block(data, &block)
  if data.is_a?(::Symbol)
    proc { |value| value.public_send(data) }
  elsif data.is_a?(::Proc)
    data
  elsif block_given?
    block
  else
    fail ArgumentError, "Expected a block, got #{data.inspect}"
  end
end
inherited(base) click to toggle source

This is a method that's called by ruby interally. We're going to use it to hook into the coercions, to allow a class coercion.

@param base [Class] A subclass. @return [void]

Calls superclass method
# File lib/mixture/coerce/base.rb, line 44
def self.inherited(base)
  super # for Singleton
  base.coerce_to(Types::Class) do |value, type|
    member = type.options.fetch(:members).first
    if member.respond_to?(:coerce) then member.coerce(value)
    elsif member.respond_to?(:new) then member.new(value)
    else
      fail CoercionError, "Expected #{member} to " \
           "respond to #coerce, #new"
    end
  end
end
to(type) click to toggle source

(see to)

# File lib/mixture/coerce/base.rb, line 117
def self.to(type)
  instance.to(type)
end
type(value = Undefined) click to toggle source

@overload type()

Returns the type this instance corresponds to.

@return [Mixture::Type]

@overload type(value)

Sets the type this instance corresponds to.

@param value [Mixture::Type]
@return [void]
# File lib/mixture/coerce/base.rb, line 22
def self.type(value = Undefined)
  if value == Undefined
    @_type
  else
    @_type = value
  end
end

Public Instance Methods

to(type) click to toggle source

Returns a block to perform the coercion to the given type. If it cannot find a coercion, it raises {CoercionError}.

@param type [Mixture::Type] The type to coerce to. @raise [CoercionError] If it could not find the coercion. @return [Proc{(Object) => Object}]

# File lib/mixture/coerce/base.rb, line 127
def to(type)
  coercions = self.class.coercions
  coercable = type.inheritable
                  .find { |ancestor| coercions.key?(ancestor) }
  unless coercable
    fail CoercionError, "Undefined coercion #{self.class.type} " \
      "=> #{type}"
  end

  public_send(coercions[coercable])
end