Class: Mixture::Coerce::Base

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/mixture/coerce/base.rb

Overview

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

Direct Known Subclasses

Array, Class, Date, DateTime, Float, Hash, Integer, Nil, Object, Rational, Set, String, Symbol, Time

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.coerce_to(to) {|value, type| ... } ⇒ void .coerce_to(to, value) ⇒ void

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

Overloads:

  • .coerce_to(to) {|value, type| ... } ⇒ void

    This method returns an undefined value.

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

    Parameters:

    Yields:

    • (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.

    Yield Parameters:

    Yield Returns:

    • (Object)

      The coerced value.

  • .coerce_to(to, value) ⇒ void

    This method returns an undefined value.

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

    Parameters:

    • to (Mixture::Types::Type)

      The type to coerce to.

    • 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.



85
86
87
88
89
90
91
92
# File 'lib/mixture/coerce/base.rb', line 85

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

.coercionsHash{Mixture::Type => Symbol}

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

Returns:



33
34
35
# File 'lib/mixture/coerce/base.rb', line 33

def self.coercions
  @_coercions ||= ThreadSafe::Hash.new
end

.data_block(data, &block) ⇒ void

This method returns an undefined value.

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

Parameters:

  • data (Proc, Symbol)

    A proc/symbol to be used for a method.



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mixture/coerce/base.rb', line 103

def self.data_block(data, &block)
  case
  when data.is_a?(::Symbol)
    proc { |value| value.public_send(data) }
  when data.is_a?(::Proc)
    data
  when block_given?
    block
  else
    fail ArgumentError, "Expected a block, got #{data.inspect}"
  end
end

.inherited(base) ⇒ void

This method returns an undefined value.

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.

Parameters:

  • base (Class)

    A subclass.



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mixture/coerce/base.rb', line 43

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) ⇒ Proc{(Object) => Object}

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

Parameters:

  • type (Mixture::Type)

    The type to coerce to.

Returns:

Raises:



117
118
119
# File 'lib/mixture/coerce/base.rb', line 117

def self.to(type)
  instance.to(type)
end

.typeMixture::Type .type(value) ⇒ void

Overloads:

  • .typeMixture::Type

    Returns the type this instance corresponds to.

    Returns:

    • (Mixture::Type)
  • .type(value) ⇒ void

    This method returns an undefined value.

    Sets the type this instance corresponds to.

    Parameters:

    • value (Mixture::Type)


21
22
23
24
25
26
27
# File 'lib/mixture/coerce/base.rb', line 21

def self.type(value = Undefined)
  if value == Undefined
    @_type
  else
    @_type = value
  end
end

Instance Method Details

#to(type) ⇒ Proc{(Object) => Object}

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

Parameters:

  • type (Mixture::Type)

    The type to coerce to.

Returns:

Raises:



127
128
129
130
131
132
133
134
135
# File 'lib/mixture/coerce/base.rb', line 127

def to(type)
  coercions = self.class.coercions
  coercable = type.inheritable
              .find { |ancestor| coercions.key?(ancestor) }
  fail CoercionError, "Undefined coercion #{self.class.type} " \
    "=> #{type}" unless coercable

  public_send(coercions[coercable])
end