y_support 2.1.18 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/y_support/all.rb +2 -32
- data/lib/y_support/core_ext/array.rb +2 -2
- data/lib/y_support/core_ext/class.rb +2 -2
- data/lib/y_support/core_ext/enumerable.rb +2 -2
- data/lib/y_support/core_ext/hash/misc.rb +23 -10
- data/lib/y_support/core_ext/hash.rb +2 -2
- data/lib/y_support/core_ext/module/misc.rb +9 -0
- data/lib/y_support/core_ext/module.rb +2 -2
- data/lib/y_support/core_ext/numeric.rb +2 -2
- data/lib/y_support/core_ext/object/inspection.rb +8 -2
- data/lib/y_support/core_ext/object.rb +3 -3
- data/lib/y_support/core_ext/string/misc.rb +9 -12
- data/lib/y_support/core_ext/string.rb +2 -2
- data/lib/y_support/core_ext/symbol.rb +2 -2
- data/lib/y_support/core_ext.rb +1 -1
- data/lib/y_support/flex_coerce/class_methods.rb +49 -0
- data/lib/y_support/flex_coerce/flex_proxy.rb +121 -0
- data/lib/y_support/flex_coerce/module_methods.rb +37 -0
- data/lib/y_support/flex_coerce.rb +24 -0
- data/lib/y_support/kde.rb +1 -1
- data/lib/y_support/literate.rb +253 -0
- data/lib/y_support/local_object.rb +1 -1
- data/lib/y_support/name_magic/array_methods.rb +48 -0
- data/lib/y_support/name_magic/class_methods.rb +205 -161
- data/lib/y_support/name_magic/hash_methods.rb +33 -0
- data/lib/y_support/name_magic/namespace.rb +449 -0
- data/lib/y_support/name_magic.rb +358 -100
- data/lib/y_support/null_object.rb +1 -1
- data/lib/y_support/respond_to.rb +1 -1
- data/lib/y_support/stdlib_ext/matrix/misc.rb +2 -2
- data/lib/y_support/stdlib_ext/matrix.rb +2 -2
- data/lib/y_support/stdlib_ext.rb +1 -1
- data/lib/y_support/typing/array.rb +1 -1
- data/lib/y_support/typing/enumerable.rb +1 -1
- data/lib/y_support/typing/hash.rb +1 -1
- data/lib/y_support/typing/module.rb +1 -1
- data/lib/y_support/typing/object/typing.rb +17 -15
- data/lib/y_support/typing/object.rb +1 -1
- data/lib/y_support/typing.rb +14 -10
- data/lib/y_support/unicode.rb +1 -1
- data/lib/y_support/version.rb +1 -1
- data/lib/y_support/x.rb +2 -1
- data/test/flex_coerce_test.rb +134 -0
- data/test/literate_test.rb +231 -0
- data/test/misc_test.rb +49 -27
- data/test/name_magic_test.rb +907 -60
- data/test/typing_test.rb +7 -7
- metadata +14 -13
- data/lib/y_support/abstract_algebra.rb +0 -234
- data/lib/y_support/name_magic/array.rb +0 -38
- data/lib/y_support/name_magic/hash.rb +0 -31
- data/lib/y_support/name_magic/namespace_methods.rb +0 -260
- data/lib/y_support/try.rb +0 -133
- data/test/abstract_algebra_test.rb +0 -138
- data/test/performance_test_example.rb +0 -23
- data/test/try_test.rb +0 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ab593edcd28581e245478b60043c42f9440086c
|
4
|
+
data.tar.gz: 4fb00fe45dcb47047877141c63c8c4c5d24d5375
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a20065557690cf1b52ce7525f54342597ad97e071e13b2236ddc5584b5084ed7551d7c86a0b8ab9a9989bdcd266abc2e6cff929aa315d3cd2cab177230fc7dc
|
7
|
+
data.tar.gz: 81d28a6721cb01c0d181d6b17524cfa22674b86fdcdc6fed1658350713fbc5c5d672c604531eec70f08ef82322e28a6df4587487dfaa3ad5579ead28ce675dda
|
data/lib/y_support/all.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
|
3
3
|
require 'y_support'
|
4
|
+
require 'y_support/flex_coerce'
|
4
5
|
require 'y_support/name_magic'
|
5
6
|
require 'y_support/typing'
|
6
7
|
require 'y_support/unicode'
|
@@ -8,38 +9,7 @@ require 'y_support/respond_to'
|
|
8
9
|
require 'y_support/null_object'
|
9
10
|
require 'y_support/inert_recorder'
|
10
11
|
require 'y_support/local_object'
|
11
|
-
require 'y_support/
|
12
|
-
require 'y_support/abstract_algebra'
|
12
|
+
require 'y_support/literate'
|
13
13
|
require 'y_support/kde'
|
14
14
|
require 'y_support/x'
|
15
15
|
require 'y_support/misc'
|
16
|
-
|
17
|
-
|
18
|
-
# # Test me!
|
19
|
-
# class BlankSlate
|
20
|
-
# class << self
|
21
|
-
# # Hide the method named +name+ in the BlankSlate class. Don't
|
22
|
-
# # hide +instance_eval+ or any method beginning with "__".
|
23
|
-
# def hide( name )
|
24
|
-
# if instance_methods.include? name and
|
25
|
-
# name !~ /^(__|instance_eval)/
|
26
|
-
# @hidden_methods ||= {}
|
27
|
-
# @hidden_methods[name] = instance_method name
|
28
|
-
# undef_method name
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
|
32
|
-
# def find_hidden_method name
|
33
|
-
# @hidden_methods ||= {}
|
34
|
-
# @hidden_methods[name] || superclass.find_hidden_method( name )
|
35
|
-
# end
|
36
|
-
|
37
|
-
# # Redefine a previously hidden method
|
38
|
-
# def reveal name
|
39
|
-
# unbound_method = find_hidden_method name
|
40
|
-
# fail "Don't know how to reveal method '#{name}'" unless unbound_method
|
41
|
-
# define_method( name, unbound_method )
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
# end # class BlankSlate
|
45
|
-
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'array/misc'
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'class/misc'
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'enumerable/misc'
|
@@ -49,16 +49,26 @@ class Hash
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
#
|
53
|
-
# 2 arguments (key: value pair) and returns the new key.
|
52
|
+
# Like #with_keys, but modifies the receiver.
|
54
53
|
#
|
55
|
-
def
|
54
|
+
def with_keys!
|
55
|
+
keys.each_with_object self do |key, hsh|
|
56
|
+
hsh[ yield key ] = delete key
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# The difference from #with_keys is that modify_keys expects
|
61
|
+
# block that takes 2 arguments (key: value pair) and returns the
|
62
|
+
# new key.
|
63
|
+
#
|
64
|
+
def change_keys
|
56
65
|
each_with_object self.class.new do |pair, hsh|
|
57
66
|
hsh[ yield pair ] = self[ pair[0] ]
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
61
|
-
# Applies a block as a mapping on all values, returning a new
|
70
|
+
# Applies a block as a mapping on all values, returning a new
|
71
|
+
# hash.
|
62
72
|
#
|
63
73
|
def with_values
|
64
74
|
each_with_object self.class.new do |(k, v), hsh| hsh[ k ] = yield v end
|
@@ -70,8 +80,9 @@ class Hash
|
|
70
80
|
each_with_object self do |(k, v), hsh| hsh[ k ] = yield v end
|
71
81
|
end
|
72
82
|
|
73
|
-
# The difference from #
|
74
|
-
# that takes 2 arguments
|
83
|
+
# The difference from #with_values is that modify_values expects
|
84
|
+
# block that takes 2 arguments [ key, value ] and returns the
|
85
|
+
# new value.
|
75
86
|
#
|
76
87
|
def modify_values
|
77
88
|
each_with_object self.class.new do |pair, hsh|
|
@@ -96,15 +107,17 @@ class Hash
|
|
96
107
|
end
|
97
108
|
end
|
98
109
|
|
99
|
-
# Checking mainly against the collision with ActiveSupport's
|
110
|
+
# Checking mainly against the collision with ActiveSupport's
|
111
|
+
# Hash#slice.
|
100
112
|
if Hash.instance_methods.include? :slice then
|
101
113
|
warn "Collision: Method #slice already defined on Hash! (%s)" %
|
102
114
|
Hash.instance_method( :slice ).source_location
|
103
115
|
end
|
104
116
|
|
105
|
-
# A bit like Array#slice, but only takes 1 argument, which is
|
106
|
-
# or an Array, and returns the selection of the
|
107
|
-
# the range or are present in the
|
117
|
+
# A bit like Array#slice, but only takes 1 argument, which is
|
118
|
+
# either a Range, or an Array, and returns the selection of the
|
119
|
+
# hash for the keys that match the range or are present in the
|
120
|
+
# array.
|
108
121
|
#
|
109
122
|
def slice matcher
|
110
123
|
self.class[ case matcher
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'hash/misc'
|
@@ -1,4 +1,13 @@
|
|
1
1
|
class Module
|
2
|
+
# Hopefully not too ridiculous attempt to call a spade a spade. In the
|
3
|
+
# 1964 landmark paper "The mechanical evaluation of expressions", Peter
|
4
|
+
# Landin has defined an abstract language which is a basic for
|
5
|
+
# expression-oriented high-level languages popular today, such as Ruby.
|
6
|
+
# While Ruby's instance variables can be called "attributes", attribute
|
7
|
+
# readers seem to be called "selectors" in Landin's paper.
|
8
|
+
#
|
9
|
+
alias selector attr_reader
|
10
|
+
|
2
11
|
# Creates a module that inherits from the receiver and is parametrized
|
3
12
|
# with the given set of parameters. The parameters have form { symbol:
|
4
13
|
# value } and they cause singleton method(s) named "symbol" be defined
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'module/misc'
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'numeric/misc'
|
@@ -1,7 +1,13 @@
|
|
1
1
|
class Object
|
2
2
|
# Constructs the string "#{self.class}:#{self}". Useful for inspection.
|
3
3
|
#
|
4
|
-
def
|
5
|
-
|
4
|
+
def y_inspect( option=nil )
|
5
|
+
case option
|
6
|
+
when :full then "#<#{y_inspect}>"
|
7
|
+
when :short then
|
8
|
+
"#{self.class.name.to_s.split( "::" ).last}:#{self}"
|
9
|
+
else
|
10
|
+
"#{self.class}:#{self}"
|
11
|
+
end
|
6
12
|
end
|
7
13
|
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'object/misc'
|
3
|
+
require_relative 'object/inspection'
|
@@ -56,26 +56,23 @@ class String
|
|
56
56
|
gsub ' ', '_'
|
57
57
|
end
|
58
58
|
|
59
|
-
# Converts a string into a
|
60
|
-
# be created from any
|
61
|
-
#
|
62
|
-
#
|
63
|
-
# superfluous spaces, and underscores the remaining ones, before returning
|
64
|
-
# the string.
|
59
|
+
# Converts a string into a string suitable as a symbol. Although symbols can
|
60
|
+
# be created from any strings, sometimes it is good to have symbols without
|
61
|
+
# accented characters, punctuation and whitespaces. This method returns a
|
62
|
+
# string of these characteristics.
|
65
63
|
#
|
66
64
|
def standardize
|
67
|
-
ς = self.
|
65
|
+
ς = self.tr( "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
|
66
|
+
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
|
67
|
+
)
|
68
68
|
",.;".each_char { |c| ς.gsub! c, " " }
|
69
|
-
ς.stripn
|
70
|
-
.squeeze(" ")
|
71
|
-
.underscore_spaces
|
69
|
+
ς.stripn.squeeze(" ").underscore_spaces
|
72
70
|
end
|
73
71
|
|
74
72
|
# Applies #standardize to the receiver and converts the result to a symbol.
|
75
73
|
#
|
76
74
|
def to_standardized_sym
|
77
|
-
standardize
|
78
|
-
.to_sym
|
75
|
+
standardize.to_sym
|
79
76
|
end
|
80
77
|
|
81
78
|
# Capitalizes a string and appends an exclamation mark. Also allows optional
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'string/misc'
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'symbol/misc'
|
data/lib/y_support/core_ext.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# This module defines class methods, with which the host class of FlexProxy
|
4
|
+
# is to be extended.
|
5
|
+
#
|
6
|
+
module FlexCoerce::ClassMethods
|
7
|
+
# Class method .coercion_table provides access to the table of coercion
|
8
|
+
# behavior specific to each host class. The table itself is a hash with
|
9
|
+
# method names as keys. Each value is an array of pairs [ type, block ],
|
10
|
+
# where type specifies the operand type, and block specifies the behavior
|
11
|
+
# when the method in question is invoked with the given operand type.
|
12
|
+
#
|
13
|
+
def coercion_table
|
14
|
+
@coercion_table ||= Hash.new { |hash, missing_key|
|
15
|
+
case missing_key
|
16
|
+
when Symbol then hash[ missing_key ] = []
|
17
|
+
else
|
18
|
+
hash[ missing_key.to_sym ]
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Class method .define_coercion allows the classes that use FlexCoerce to
|
24
|
+
# define custom coercion for certain symbols. The method expects: (1)
|
25
|
+
# object type (or a list of object types), (2) +:method+ parameter
|
26
|
+
# specifying the method(s) for which coercion is being defined, and (3) a
|
27
|
+
# block that defines the operation. The block should take 2 ordered
|
28
|
+
# arguments, representing first and second operand. The first operand is
|
29
|
+
# the object that invoked #coerce method, the second operand is an
|
30
|
+
# instance of the receiver class. Example:
|
31
|
+
#
|
32
|
+
# define_coercion Integer, method: :* do |operand1, operand2|
|
33
|
+
# operand2 * operand1 # swap the operands
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
def define_coercion *types,
|
37
|
+
method: fail( ArgumentError, "When defining coercion, " +
|
38
|
+
"method must be given!" ),
|
39
|
+
&block
|
40
|
+
unless block.arity == 2
|
41
|
+
fail ArgumentError, "The supplied block, which defines operation" +
|
42
|
+
"#{method}, must take exactly 2 arguments!"
|
43
|
+
end
|
44
|
+
# For each type, add one line to the coercion_table entry.
|
45
|
+
types.each do |type|
|
46
|
+
coercion_table[ method ] << [ type, block ]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# In FlexCoerce, #coerce method of the host class is made to return a pair
|
4
|
+
# [ proxy, receiver ], where proxy is an object of FlexProxy class. As name
|
5
|
+
# suggests, proxy represents and wraps argument that has been supplied to
|
6
|
+
# #coerce method. This gives the user the opportunity to teach the proxy to
|
7
|
+
# correctly respond to various operators (#+, #-, #*, #/,...) and other
|
8
|
+
# methods. Instances of FlexProxy are essentially a single-use objects –
|
9
|
+
# they respond to a single message, after which their life should end.
|
10
|
+
#
|
11
|
+
class FlexCoerce::FlexProxy
|
12
|
+
class << self
|
13
|
+
alias of new # allows statements such as FlexProxy.of( first_operand )
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :operand
|
17
|
+
|
18
|
+
# Method #host_class is delegated to self.class. It refers to the
|
19
|
+
# host class to which a parametrized subclass of FlexProxy belongs.
|
20
|
+
#
|
21
|
+
def host_class
|
22
|
+
self.class.host_class
|
23
|
+
end
|
24
|
+
|
25
|
+
# The constructor of FlexProxy requires only one parameter: The first operand
|
26
|
+
# which has been supplied to #coerce method.
|
27
|
+
#
|
28
|
+
def initialize first_operand
|
29
|
+
@operand = first_operand
|
30
|
+
end
|
31
|
+
|
32
|
+
# Proxy is essentially a single-use object. In its life, it receives a single
|
33
|
+
# message and returning the result. Unless the user specifically orders
|
34
|
+
# FlexProxy to respond to a method, it should raise TypeError.
|
35
|
+
#
|
36
|
+
def method_missing ß, arg
|
37
|
+
table_entry = host_class.coercion_table[ ß ]
|
38
|
+
response = table_entry.find { |type, closure| type === operand }
|
39
|
+
fail TypeError, "#{operand.class} not compatible with " +
|
40
|
+
"#{arg.class} and ##{ß} method!" unless response
|
41
|
+
response[ 1 ].call( operand, arg )
|
42
|
+
end
|
43
|
+
|
44
|
+
# Basic form of Proxy#+ method simply raises TypeError. The user is expected
|
45
|
+
# to override this method as necessary.
|
46
|
+
#
|
47
|
+
def + arg
|
48
|
+
table_entry = host_class.coercion_table[ :+ ]
|
49
|
+
response = table_entry.find { |type, closure| type === operand } or
|
50
|
+
fail TypeError, "#{arg.class} cannot be added to a #{operand.class}!"
|
51
|
+
response[ 1 ].call( operand, arg )
|
52
|
+
end
|
53
|
+
|
54
|
+
# Basic form of Proxy#- method simply raises TypeError. The user is expected
|
55
|
+
# to override this method as necessary.
|
56
|
+
#
|
57
|
+
def - arg
|
58
|
+
table_entry = host_class.coercion_table[ :- ]
|
59
|
+
response = table_entry.find { |type, closure| type === operand } or
|
60
|
+
fail TypeError, "#{arg.class} cannot be subtracted " +
|
61
|
+
"from a #{operand.class}!"
|
62
|
+
response[ 1 ].call( operand, arg )
|
63
|
+
end
|
64
|
+
|
65
|
+
# Basic form of Proxy#* method simply raises TypeError. The user is expected
|
66
|
+
# to override this method as necessary.
|
67
|
+
#
|
68
|
+
def * arg
|
69
|
+
table_entry = host_class.coercion_table[ :* ]
|
70
|
+
response = table_entry.find { |type, closure| type === operand } or
|
71
|
+
fail TypeError, "#{operand.class} cannot be multiplied " +
|
72
|
+
"by a #{arg.class}!"
|
73
|
+
response[ 1 ].call( operand, arg )
|
74
|
+
end
|
75
|
+
|
76
|
+
# Basic form of Proxy#/ method simply raises TypeError. The user is expected
|
77
|
+
# to override this method as necessary.
|
78
|
+
#
|
79
|
+
def / arg
|
80
|
+
table_entry = host_class.coercion_table[ :/ ]
|
81
|
+
response = table_entry.find { |type, closure| type === operand } or
|
82
|
+
fail TypeError, "#{arg.class} cannot be divided by a #{operand.class}!"
|
83
|
+
response[ 1 ].call( operand, arg )
|
84
|
+
end
|
85
|
+
|
86
|
+
# Basic form of Proxy#** method simply raises TypeError. The user is expected
|
87
|
+
# to override this method as necessary.
|
88
|
+
#
|
89
|
+
def ** arg
|
90
|
+
table_entry = host_class.coercion_table[ :** ]
|
91
|
+
response = table_entry.find { |type, closure| type === operand } or
|
92
|
+
fail TypeError, "#{arg.class} cannot be raised to a #{operand.class}!"
|
93
|
+
response[ 1 ].call( operand, arg )
|
94
|
+
end
|
95
|
+
|
96
|
+
# For less common operators, methods raising TypeError are defined below.
|
97
|
+
# Again, the user is expected to override them whenever necessary.
|
98
|
+
#
|
99
|
+
[ :%,
|
100
|
+
:div,
|
101
|
+
:divmod,
|
102
|
+
:fdiv,
|
103
|
+
:&,
|
104
|
+
:|,
|
105
|
+
:^,
|
106
|
+
:>,
|
107
|
+
:>=,
|
108
|
+
:<,
|
109
|
+
:<=,
|
110
|
+
:<=>,
|
111
|
+
:=== # Operator === is mostly too liberal to call coerce.
|
112
|
+
].each do |binary_operator|
|
113
|
+
define_method binary_operator do |arg|
|
114
|
+
table_entry = host_class.coercion_table[ binary_operator ]
|
115
|
+
response = table_entry.find { |type, closure| type === operand } or
|
116
|
+
fail TypeError, "#{arg.class} is not compatible with #{operand.class} " +
|
117
|
+
"and binary operator ##{binary_operator}"
|
118
|
+
response[ 1 ].call( operand, arg )
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end # class FlexCoerce::FlexProxy
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# This module contains methods with which FlexProxy and modules which include
|
4
|
+
# it are to be extended.
|
5
|
+
#
|
6
|
+
module FlexCoerce::ModuleMethods
|
7
|
+
# This method customizes the host class in which FlexCoerce is included
|
8
|
+
# by setting up a parametrized subclass of FlexCoerce::FlexProxy and
|
9
|
+
# extending the host class with FlexCoerce::ClassMethods.
|
10
|
+
#
|
11
|
+
def customize_class host_class
|
12
|
+
host_class.instance_exec do
|
13
|
+
# Set up a parametrized subclass of FlexCoerce::FlexProxy
|
14
|
+
param_class!( { FlexProxy: FlexCoerce::FlexProxy },
|
15
|
+
with: { host_class: host_class } )
|
16
|
+
end
|
17
|
+
host_class.extend FlexCoerce::ClassMethods
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method customizes a module in which FlexCoerce is included by extending
|
21
|
+
# it with FlexCoerce::ModuleMethods.
|
22
|
+
#
|
23
|
+
def customize_module host_module
|
24
|
+
host_module.extend FlexCoerce::ModuleMethods
|
25
|
+
end
|
26
|
+
|
27
|
+
# Hook method which is invoked whenever a module is included in another module
|
28
|
+
# (or class, which is also a module).
|
29
|
+
#
|
30
|
+
def included receiver
|
31
|
+
if receiver.is_a? Class then # we have reached the host class
|
32
|
+
customize_class( receiver )
|
33
|
+
else # receiver is a Module
|
34
|
+
customize_module( receiver )
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative 'core_ext/object'
|
4
|
+
|
5
|
+
module FlexCoerce
|
6
|
+
require_relative 'flex_coerce/flex_proxy'
|
7
|
+
require_relative 'flex_coerce/class_methods'
|
8
|
+
require_relative 'flex_coerce/module_methods'
|
9
|
+
|
10
|
+
extend FlexCoerce::ModuleMethods
|
11
|
+
|
12
|
+
# Method #FlexProxy is delegated to the host class, it returns the
|
13
|
+
# parametrized subclass of FlexCoerce::FlexProxy specific to the host class.
|
14
|
+
#
|
15
|
+
def FlexProxy
|
16
|
+
self.class.FlexProxy
|
17
|
+
end
|
18
|
+
|
19
|
+
# FlexCoerce provides coerce method that returns a proxy object and self.
|
20
|
+
#
|
21
|
+
def coerce first_operand
|
22
|
+
return FlexProxy().of( first_operand ), self
|
23
|
+
end
|
24
|
+
end
|