Class: FlexCoerce::FlexProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/y_support/flex_coerce/flex_proxy.rb

Overview

In FlexCoerce, #coerce method of the host class is made to return a pair [ proxy, receiver ], where proxy is an object of FlexProxy class. As name suggests, proxy represents and wraps argument that has been supplied to #coerce method. This gives the user the opportunity to teach the proxy to correctly respond to various operators (#+, #-, #*, #/,…) and other methods. Instances of FlexProxy are essentially a single-use objects – they respond to a single message, after which their life should end.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(first_operand) ⇒ FlexProxy

The constructor of FlexProxy requires only one parameter: The first operand which has been supplied to #coerce method.



28
29
30
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 28

def initialize first_operand
  @operand = first_operand
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(ß, arg) ⇒ Object

Proxy is essentially a single-use object. In its life, it receives a single message and returning the result. Unless the user specifically orders FlexProxy to respond to a method, it should raise TypeError.



36
37
38
39
40
41
42
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 36

def method_missing ß, arg
  table_entry = host_class.coercion_table[ ß ]
  response = table_entry.find { |type, closure| type === operand }
  fail TypeError, "#{operand.class} not compatible with " +
                  "#{arg.class} and ##{ß} method!" unless response
  response[ 1 ].call( operand, arg )
end

Instance Attribute Details

#operandObject (readonly)

Returns the value of attribute operand.



16
17
18
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 16

def operand
  @operand
end

Instance Method Details

#*(arg) ⇒ Object

Basic form of Proxy#* method simply raises TypeError. The user is expected to override this method as necessary.



68
69
70
71
72
73
74
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 68

def * arg
  table_entry = host_class.coercion_table[ :* ]
  response = table_entry.find { |type, closure| type === operand } or
    fail TypeError, "#{operand.class} cannot be multiplied " +
                    "by a #{arg.class}!"
  response[ 1 ].call( operand, arg )
end

#**(arg) ⇒ Object

Basic form of Proxy#** method simply raises TypeError. The user is expected to override this method as necessary.



89
90
91
92
93
94
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 89

def ** arg
  table_entry = host_class.coercion_table[ :** ]
  response = table_entry.find { |type, closure| type === operand } or
    fail TypeError, "#{arg.class} cannot be raised to a #{operand.class}!"
  response[ 1 ].call( operand, arg )
end

#+(arg) ⇒ Object

Basic form of Proxy#+ method simply raises TypeError. The user is expected to override this method as necessary.



47
48
49
50
51
52
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 47

def + arg
  table_entry = host_class.coercion_table[ :+ ]
  response = table_entry.find { |type, closure| type === operand } or
    fail TypeError, "#{arg.class} cannot be added to a #{operand.class}!"
  response[ 1 ].call( operand, arg )
end

#-(arg) ⇒ Object

Basic form of Proxy#- method simply raises TypeError. The user is expected to override this method as necessary.



57
58
59
60
61
62
63
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 57

def - arg
  table_entry = host_class.coercion_table[ :- ]
  response = table_entry.find { |type, closure| type === operand } or
    fail TypeError, "#{arg.class} cannot be subtracted " +
                    "from a #{operand.class}!"
  response[ 1 ].call( operand, arg )
end

#/(arg) ⇒ Object

Basic form of Proxy#/ method simply raises TypeError. The user is expected to override this method as necessary.



79
80
81
82
83
84
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 79

def / arg
  table_entry = host_class.coercion_table[ :/ ]
  response = table_entry.find { |type, closure| type === operand } or
    fail TypeError, "#{arg.class} cannot be divided by a #{operand.class}!"
  response[ 1 ].call( operand, arg )
end

#host_classObject

Method #host_class is delegated to self.class. It refers to the host class to which a parametrized subclass of FlexProxy belongs.



21
22
23
# File 'lib/y_support/flex_coerce/flex_proxy.rb', line 21

def host_class
  self.class.host_class
end