casting 0.5.0 → 0.5.2
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 +7 -0
- data/lib/casting.rb +11 -171
- data/lib/casting/client.rb +41 -0
- data/lib/casting/delegation.rb +32 -0
- data/lib/casting/missing_method_client.rb +42 -0
- data/lib/casting/prepared_delegation.rb +90 -0
- data/lib/casting/version.rb +1 -1
- data/test/casting_19_test.rb +0 -9
- data/test/casting_test.rb +16 -94
- data/test/client_test.rb +42 -0
- data/test/delegation_test.rb +61 -0
- data/test/missing_method_client_test.rb +53 -0
- metadata +25 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 475b68274fd553b6f0f42332623d2d13e3668198
|
4
|
+
data.tar.gz: ce58705b237fed2f09d4ea34d45315745c662e8a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dd71a1d2f4ef744f27c885b8f3b5a71a4c06585b51fa4344010da8334864ce626a66a738716873051990ae0ecc1d0bee8de121ceb81f5bbdfa73755a6a70e501
|
7
|
+
data.tar.gz: 48703d09ddf47127c7f8b3bc2d36059bcf9ab6988ed6c360607fae501229000c4e72a26df490d4f69f9e23e48c8a2fa0e2bfc6c1d57e7fbd4e88bd5b8e6d5ac9
|
data/lib/casting.rb
CHANGED
@@ -1,190 +1,30 @@
|
|
1
|
-
require '
|
1
|
+
require 'casting/client'
|
2
2
|
|
3
3
|
module Casting
|
4
4
|
|
5
|
+
class InvalidClientError < StandardError; end
|
6
|
+
|
5
7
|
def self.delegating(assignments)
|
6
8
|
assignments.each do |object, mod|
|
7
|
-
object
|
8
|
-
object.send(:instance_variable_set, :@__current_delegate__, mod)
|
9
|
+
cast_object(object, mod)
|
9
10
|
end
|
10
11
|
yield
|
11
12
|
ensure
|
12
13
|
assignments.each do |object, mod|
|
13
|
-
|
14
|
-
object.send(:remove_instance_variable, :@__previous_delegate__)
|
14
|
+
uncast_object(object)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
"You must set your attendant object using `to'."
|
21
|
-
end
|
22
|
-
end
|
18
|
+
def self.cast_object(object, mod)
|
19
|
+
raise InvalidClientError.new unless object.respond_to?(:cast_as)
|
23
20
|
|
24
|
-
|
21
|
+
object.cast_as(mod)
|
25
22
|
end
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
def self.included(base)
|
30
|
-
def base.delegate_missing_methods
|
31
|
-
self.send(:include, ::Casting::MissingMethodClient)
|
32
|
-
end
|
33
|
-
|
34
|
-
unless base.instance_methods.include?('delegate')
|
35
|
-
base.class_eval{ alias_method :delegate, :cast }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.extended(base)
|
40
|
-
unless base.respond_to?('delegate')
|
41
|
-
base.singleton_class.class_eval{ alias_method :delegate, :cast }
|
42
|
-
end
|
43
|
-
end
|
24
|
+
def self.uncast_object(object)
|
25
|
+
return unless object.respond_to?(:uncast)
|
44
26
|
|
45
|
-
|
46
|
-
Casting::Delegation.new(delegated_method_name, self)
|
47
|
-
end
|
48
|
-
|
49
|
-
def cast(delegated_method_name, attendant, *args)
|
50
|
-
delegation(delegated_method_name).to(attendant).with(*args).call
|
51
|
-
end
|
52
|
-
|
53
|
-
def delegate_missing_methods
|
54
|
-
self.extend ::Casting::MissingMethodClient
|
55
|
-
end
|
27
|
+
object.uncast
|
56
28
|
end
|
57
29
|
|
58
|
-
module MissingMethodClient
|
59
|
-
def method_missing(meth, *args, &block)
|
60
|
-
if delegate_has_method?(meth)
|
61
|
-
delegate(meth, @__current_delegate__, *args, &block)
|
62
|
-
else
|
63
|
-
super
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def respond_to_missing?(meth, *)
|
68
|
-
delegate_has_method?(meth) || super
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def delegate_has_method?(meth)
|
74
|
-
return false unless @__current_delegate__
|
75
|
-
|
76
|
-
if Module === @__current_delegate__
|
77
|
-
@__current_delegate__.instance_methods
|
78
|
-
else
|
79
|
-
@__current_delegate__.methods
|
80
|
-
end.include?(meth)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
class PreparedDelegation
|
85
|
-
|
86
|
-
attr_reader :client
|
87
|
-
attr_reader :delegated_method_name, :attendant, :arguments
|
88
|
-
private :delegated_method_name, :attendant, :arguments
|
89
|
-
|
90
|
-
def initialize(settings)
|
91
|
-
@delegated_method_name = settings[:delegated_method_name]
|
92
|
-
@client = settings[:client]
|
93
|
-
@attendant = settings[:attendant]
|
94
|
-
@arguments = settings[:arguments]
|
95
|
-
end
|
96
|
-
|
97
|
-
def to(object_or_module)
|
98
|
-
@attendant = method_carrier(object_or_module)
|
99
|
-
begin
|
100
|
-
check_valid_type
|
101
|
-
rescue TypeError => e
|
102
|
-
raise unless RedCard.check '2.0'
|
103
|
-
@attendant = method_module || raise
|
104
|
-
end
|
105
|
-
self
|
106
|
-
end
|
107
|
-
|
108
|
-
def with(*args)
|
109
|
-
@arguments = args
|
110
|
-
self
|
111
|
-
end
|
112
|
-
|
113
|
-
def call(*args)
|
114
|
-
@arguments = args unless args.empty?
|
115
|
-
raise MissingAttendant.new unless attendant
|
116
|
-
|
117
|
-
if arguments
|
118
|
-
delegated_method.bind(client).call(*arguments)
|
119
|
-
else
|
120
|
-
delegated_method.bind(client).call
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
|
126
|
-
def check_valid_type
|
127
|
-
begin
|
128
|
-
!client.nil? && delegated_method.bind(client)
|
129
|
-
rescue TypeError => e
|
130
|
-
raise TypeError.new("`to' argument must be a module or an instance of #{client.class}")
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def method_carrier(object_or_module)
|
135
|
-
if Module === object_or_module
|
136
|
-
if RedCard.check '2.0'
|
137
|
-
object_or_module
|
138
|
-
else
|
139
|
-
client.clone.extend(object_or_module)
|
140
|
-
end
|
141
|
-
else
|
142
|
-
object_or_module
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def method_module
|
147
|
-
delegated_method.owner unless delegated_method.owner.is_a?(Class)
|
148
|
-
end
|
149
|
-
|
150
|
-
def delegated_method
|
151
|
-
if Module === attendant
|
152
|
-
attendant.instance_method(delegated_method_name)
|
153
|
-
else
|
154
|
-
attendant.method(delegated_method_name).unbind
|
155
|
-
end
|
156
|
-
rescue NameError => e
|
157
|
-
raise InvalidAttendant.new(e.message)
|
158
|
-
end
|
159
|
-
|
160
|
-
end
|
161
|
-
|
162
|
-
class Delegation
|
163
|
-
|
164
|
-
attr_reader :prepared_delegation
|
165
|
-
private :prepared_delegation
|
166
|
-
|
167
|
-
def initialize(delegated_method_name, client)
|
168
|
-
@prepared_delegation = PreparedDelegation.new(:delegated_method_name => delegated_method_name, :client => client)
|
169
|
-
end
|
170
|
-
|
171
|
-
def client
|
172
|
-
prepared_delegation.client
|
173
|
-
end
|
174
|
-
|
175
|
-
def to(object_or_module)
|
176
|
-
prepared_delegation.to(object_or_module)
|
177
|
-
self
|
178
|
-
end
|
179
|
-
|
180
|
-
def with(*args)
|
181
|
-
prepared_delegation.with(*args)
|
182
|
-
self
|
183
|
-
end
|
184
|
-
|
185
|
-
def call(*args)
|
186
|
-
prepared_delegation.call(*args)
|
187
|
-
end
|
188
|
-
|
189
|
-
end
|
190
30
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'casting/delegation'
|
2
|
+
require 'casting/missing_method_client'
|
3
|
+
|
4
|
+
module Casting
|
5
|
+
module Client
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
def base.delegate_missing_methods
|
9
|
+
self.send(:include, ::Casting::MissingMethodClient)
|
10
|
+
end
|
11
|
+
|
12
|
+
unless base.instance_methods.include?('delegate')
|
13
|
+
add_delegate_method_to(base)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.extended(base)
|
18
|
+
unless base.respond_to?('delegate')
|
19
|
+
add_delegate_method_to(base.singleton_class)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def delegation(delegated_method_name)
|
24
|
+
Casting::Delegation.new(delegated_method_name, self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def cast(delegated_method_name, attendant, *args)
|
28
|
+
delegation(delegated_method_name).to(attendant).with(*args).call
|
29
|
+
end
|
30
|
+
|
31
|
+
def delegate_missing_methods
|
32
|
+
self.extend ::Casting::MissingMethodClient
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def self.add_delegate_method_to(base)
|
38
|
+
base.class_eval{ alias_method :delegate, :cast }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'casting/prepared_delegation'
|
2
|
+
|
3
|
+
module Casting
|
4
|
+
class Delegation
|
5
|
+
|
6
|
+
attr_reader :prepared_delegation
|
7
|
+
private :prepared_delegation
|
8
|
+
|
9
|
+
def initialize(delegated_method_name, client)
|
10
|
+
@prepared_delegation = PreparedDelegation.new(:delegated_method_name => delegated_method_name, :client => client)
|
11
|
+
end
|
12
|
+
|
13
|
+
def client
|
14
|
+
prepared_delegation.client
|
15
|
+
end
|
16
|
+
|
17
|
+
def to(object_or_module)
|
18
|
+
prepared_delegation.to(object_or_module)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def with(*args)
|
23
|
+
prepared_delegation.with(*args)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(*args)
|
28
|
+
prepared_delegation.call(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Casting
|
2
|
+
module MissingMethodClient
|
3
|
+
|
4
|
+
def cast_as(attendant)
|
5
|
+
__delegates__.unshift(attendant)
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def uncast
|
10
|
+
__delegates__.shift
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(meth, *args, &block)
|
15
|
+
if !!method_delegate(meth)
|
16
|
+
delegate(meth, method_delegate(meth), *args, &block)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to_missing?(meth, *)
|
23
|
+
!!method_delegate(meth) || super
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def __delegates__
|
29
|
+
@__delegates__ ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_delegate(meth)
|
33
|
+
__delegates__.find{|attendant|
|
34
|
+
if Module === attendant
|
35
|
+
attendant.instance_methods
|
36
|
+
else
|
37
|
+
attendant.methods
|
38
|
+
end.include?(meth)
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'redcard'
|
2
|
+
|
3
|
+
module Casting
|
4
|
+
|
5
|
+
class MissingAttendant < StandardError
|
6
|
+
def message
|
7
|
+
"You must set your attendant object using `to'."
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class InvalidAttendant < StandardError; end
|
12
|
+
|
13
|
+
class PreparedDelegation
|
14
|
+
|
15
|
+
attr_reader :client
|
16
|
+
attr_reader :delegated_method_name, :attendant, :arguments
|
17
|
+
private :delegated_method_name, :attendant, :arguments
|
18
|
+
|
19
|
+
def initialize(settings)
|
20
|
+
@delegated_method_name = settings[:delegated_method_name]
|
21
|
+
@client = settings[:client]
|
22
|
+
@attendant = settings[:attendant]
|
23
|
+
@arguments = settings[:arguments]
|
24
|
+
end
|
25
|
+
|
26
|
+
def to(object_or_module)
|
27
|
+
@attendant = method_carrier(object_or_module)
|
28
|
+
begin
|
29
|
+
check_valid_type
|
30
|
+
rescue TypeError => e
|
31
|
+
raise unless RedCard.check '2.0'
|
32
|
+
@attendant = method_module || raise
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def with(*args)
|
38
|
+
@arguments = args
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def call(*args)
|
43
|
+
@arguments = args unless args.empty?
|
44
|
+
raise MissingAttendant.new unless attendant
|
45
|
+
|
46
|
+
if arguments
|
47
|
+
delegated_method.bind(client).call(*arguments)
|
48
|
+
else
|
49
|
+
delegated_method.bind(client).call
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def check_valid_type
|
56
|
+
begin
|
57
|
+
!client.nil? && delegated_method.bind(client)
|
58
|
+
rescue TypeError => e
|
59
|
+
raise TypeError.new("`to' argument must be a module or an instance of #{client.class}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def method_carrier(object_or_module)
|
64
|
+
if Module === object_or_module
|
65
|
+
if RedCard.check '2.0'
|
66
|
+
object_or_module
|
67
|
+
else
|
68
|
+
client.clone.extend(object_or_module)
|
69
|
+
end
|
70
|
+
else
|
71
|
+
object_or_module
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def method_module
|
76
|
+
delegated_method.owner unless delegated_method.owner.is_a?(Class)
|
77
|
+
end
|
78
|
+
|
79
|
+
def delegated_method
|
80
|
+
if Module === attendant
|
81
|
+
attendant.instance_method(delegated_method_name)
|
82
|
+
else
|
83
|
+
attendant.method(delegated_method_name).unbind
|
84
|
+
end
|
85
|
+
rescue NameError => e
|
86
|
+
raise InvalidAttendant.new(e.message)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
data/lib/casting/version.rb
CHANGED
data/test/casting_19_test.rb
CHANGED
@@ -26,15 +26,6 @@ end
|
|
26
26
|
|
27
27
|
describe Casting::Delegation do
|
28
28
|
|
29
|
-
# it 'errors with a method defined on another object not of the same module type' do
|
30
|
-
# client = test_person
|
31
|
-
# attendant = test_person
|
32
|
-
# attendant.extend(TestPerson::Greeter)
|
33
|
-
# assert_raises(TypeError){
|
34
|
-
# Casting::Delegation.new('greet', client).to(attendant)
|
35
|
-
# }
|
36
|
-
# end
|
37
|
-
|
38
29
|
it 'calls a method defined on another object of the same type' do
|
39
30
|
client = test_person
|
40
31
|
attendant = test_person
|
data/test/casting_test.rb
CHANGED
@@ -6,7 +6,7 @@ BlockTestPerson.send(:include, Casting::Client)
|
|
6
6
|
BlockTestPerson.delegate_missing_methods
|
7
7
|
|
8
8
|
describe Casting, '.delegating' do
|
9
|
-
it 'delegates missing methods for the objects
|
9
|
+
it 'delegates missing methods for the objects inside the block' do
|
10
10
|
client = BlockTestPerson.new('Jim')
|
11
11
|
verbose_client = BlockTestPerson.new('Amy')
|
12
12
|
|
@@ -49,105 +49,27 @@ describe Casting, '.delegating' do
|
|
49
49
|
|
50
50
|
assert !client.respond_to?(:greet)
|
51
51
|
end
|
52
|
-
end
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
it 'initializes with method name and object' do
|
57
|
-
assert Casting::Delegation.new('some_method', Object.new)
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'raises an error when calling without an attendant object' do
|
61
|
-
delegation = Casting::Delegation.new('some_method', Object.new)
|
62
|
-
assert_raises(Casting::MissingAttendant){
|
63
|
-
delegation.call
|
64
|
-
}
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'raises an error when setting an invalid attendant type' do
|
68
|
-
delegation = Casting::Delegation.new('some_method', TestPerson.new)
|
69
|
-
assert_raises(Casting::InvalidAttendant){
|
70
|
-
delegation.to(Unrelated.new)
|
71
|
-
}
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'sets an attendant to an object of an ancestor class of the object class' do
|
75
|
-
attendant = test_person
|
76
|
-
client = SubTestPerson.new
|
77
|
-
|
78
|
-
delegation = Casting::Delegation.new('name', client)
|
79
|
-
assert delegation.to(attendant)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'delegates when given a module' do
|
83
|
-
client = test_person
|
84
|
-
delegation = Casting::Delegation.new('greet', client).to(TestPerson::Greeter)
|
85
|
-
assert_equal 'hello', delegation.call
|
86
|
-
end
|
53
|
+
it 'raises an error if the given object is not an object that delegates missing methods' do
|
54
|
+
client = test_person.extend(Casting::Client)
|
87
55
|
|
88
|
-
|
89
|
-
|
90
|
-
assert_raises(TypeError){
|
91
|
-
Casting::Delegation.new('class_defined', client).to(Unrelated)
|
56
|
+
assert_raises(Casting::InvalidClientError){
|
57
|
+
Casting.delegating(client => TestPerson::Greeter){ }
|
92
58
|
}
|
93
59
|
end
|
94
60
|
|
95
|
-
it '
|
96
|
-
client = test_person
|
97
|
-
|
98
|
-
|
99
|
-
delegation = Casting::Delegation.new('verbose', client).to(attendant)
|
100
|
-
|
101
|
-
assert_equal 'hello,goodbye', delegation.with('hello', 'goodbye').call
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'prefers `call` arguments over `with`' do
|
105
|
-
client = test_person
|
106
|
-
attendant = TestPerson::Verbose
|
107
|
-
|
108
|
-
delegation = Casting::Delegation.new('verbose', client).to(attendant)
|
109
|
-
|
110
|
-
assert_equal 'call,args', delegation.with('hello', 'goodbye').call('call','args')
|
111
|
-
end
|
112
|
-
end
|
61
|
+
it 'allows for nested delegating' do
|
62
|
+
client = test_person.extend(Casting::Client)
|
63
|
+
client.delegate_missing_methods
|
113
64
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
65
|
+
Casting.delegating(client => TestPerson::Greeter) do
|
66
|
+
assert client.respond_to?(:greet)
|
67
|
+
Casting.delegating(client => TestPerson::Verbose) do
|
68
|
+
assert client.respond_to?(:greet)
|
69
|
+
assert client.respond_to?(:verbose)
|
70
|
+
end
|
71
|
+
assert !client.respond_to?(:verbose)
|
119
72
|
end
|
120
|
-
client.
|
121
|
-
|
122
|
-
attendant = TestPerson::Greeter
|
123
|
-
|
124
|
-
assert_equal 'existing delegate method', client.delegate
|
125
|
-
|
126
|
-
assert_equal 'hello', client.cast('greet', attendant)
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'adds a delegate method to call a method on an attendant' do
|
130
|
-
client = TestPerson.new
|
131
|
-
client.extend(Casting::Client)
|
132
|
-
attendant = TestPerson::Greeter
|
133
|
-
|
134
|
-
assert_equal 'hello', client.delegate('greet', attendant)
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'passes additional parameters to the attendant' do
|
138
|
-
client = TestPerson.new
|
139
|
-
client.extend(Casting::Client)
|
140
|
-
attendant = TestPerson::Verbose
|
141
|
-
|
142
|
-
assert_equal 'hello,goodbye', client.delegate('verbose', attendant, 'hello', 'goodbye')
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'passes the object as the client for delegation' do
|
146
|
-
client = Object.new
|
147
|
-
client.extend(Casting::Client)
|
148
|
-
|
149
|
-
delegation = client.delegation('id')
|
150
|
-
|
151
|
-
assert_equal client, delegation.client
|
73
|
+
assert !client.respond_to?(:greet)
|
152
74
|
end
|
153
75
|
end
|
data/test/client_test.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Casting::Client do
|
4
|
+
it 'will not override an existing `delegate` method' do
|
5
|
+
client = TestPerson.new
|
6
|
+
def client.delegate
|
7
|
+
'existing delegate method'
|
8
|
+
end
|
9
|
+
client.extend(Casting::Client)
|
10
|
+
|
11
|
+
attendant = TestPerson::Greeter
|
12
|
+
|
13
|
+
assert_equal 'existing delegate method', client.delegate
|
14
|
+
|
15
|
+
assert_equal 'hello', client.cast('greet', attendant)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'adds a delegate method to call a method on an attendant' do
|
19
|
+
client = TestPerson.new
|
20
|
+
client.extend(Casting::Client)
|
21
|
+
attendant = TestPerson::Greeter
|
22
|
+
|
23
|
+
assert_equal 'hello', client.delegate('greet', attendant)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'passes additional parameters to the attendant' do
|
27
|
+
client = TestPerson.new
|
28
|
+
client.extend(Casting::Client)
|
29
|
+
attendant = TestPerson::Verbose
|
30
|
+
|
31
|
+
assert_equal 'hello,goodbye', client.delegate('verbose', attendant, 'hello', 'goodbye')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'passes the object as the client for delegation' do
|
35
|
+
client = Object.new
|
36
|
+
client.extend(Casting::Client)
|
37
|
+
|
38
|
+
delegation = client.delegation('id')
|
39
|
+
|
40
|
+
assert_equal client, delegation.client
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Casting::Delegation do
|
4
|
+
|
5
|
+
it 'initializes with method name and object' do
|
6
|
+
assert Casting::Delegation.new('some_method', Object.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'raises an error when calling without an attendant object' do
|
10
|
+
delegation = Casting::Delegation.new('some_method', Object.new)
|
11
|
+
assert_raises(Casting::MissingAttendant){
|
12
|
+
delegation.call
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'raises an error when setting an invalid attendant type' do
|
17
|
+
delegation = Casting::Delegation.new('some_method', TestPerson.new)
|
18
|
+
assert_raises(Casting::InvalidAttendant){
|
19
|
+
delegation.to(Unrelated.new)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'sets an attendant to an object of an ancestor class of the object class' do
|
24
|
+
attendant = test_person
|
25
|
+
client = SubTestPerson.new
|
26
|
+
|
27
|
+
delegation = Casting::Delegation.new('name', client)
|
28
|
+
assert delegation.to(attendant)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'delegates when given a module' do
|
32
|
+
client = test_person
|
33
|
+
delegation = Casting::Delegation.new('greet', client).to(TestPerson::Greeter)
|
34
|
+
assert_equal 'hello', delegation.call
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not delegate when given a class' do
|
38
|
+
client = test_person
|
39
|
+
assert_raises(TypeError){
|
40
|
+
Casting::Delegation.new('class_defined', client).to(Unrelated)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'assigns arguments to the delegated method using with' do
|
45
|
+
client = test_person
|
46
|
+
attendant = TestPerson::Verbose
|
47
|
+
|
48
|
+
delegation = Casting::Delegation.new('verbose', client).to(attendant)
|
49
|
+
|
50
|
+
assert_equal 'hello,goodbye', delegation.with('hello', 'goodbye').call
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'prefers `call` arguments over `with`' do
|
54
|
+
client = test_person
|
55
|
+
attendant = TestPerson::Verbose
|
56
|
+
|
57
|
+
delegation = Casting::Delegation.new('verbose', client).to(attendant)
|
58
|
+
|
59
|
+
assert_equal 'call,args', delegation.with('hello', 'goodbye').call('call','args')
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'casting/client'
|
3
|
+
|
4
|
+
describe Casting::MissingMethodClient, '#cast_as' do
|
5
|
+
def client
|
6
|
+
@client ||= test_person.extend(Casting::Client, Casting::MissingMethodClient)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "sets the object's delegate for missing methods" do
|
10
|
+
client.cast_as(TestPerson::Greeter)
|
11
|
+
assert_equal 'hello', client.greet
|
12
|
+
end
|
13
|
+
|
14
|
+
it "delegates to objects of the same type" do
|
15
|
+
client.extend(TestPerson::Greeter)
|
16
|
+
attendant = client.clone
|
17
|
+
client.singleton_class.send(:undef_method, :greet)
|
18
|
+
client.cast_as(attendant)
|
19
|
+
assert_equal 'hello', client.greet
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the object for further operation" do
|
23
|
+
jim = test_person.extend(Casting::Client, Casting::MissingMethodClient)
|
24
|
+
|
25
|
+
assert_equal 'hello', jim.cast_as(TestPerson::Greeter).greet
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe Casting::MissingMethodClient, '#uncast' do
|
30
|
+
def client
|
31
|
+
@client ||= test_person.extend(Casting::Client, Casting::MissingMethodClient)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "removes the last added delegate" do
|
35
|
+
client.cast_as(TestPerson::Greeter)
|
36
|
+
assert_equal 'hello', client.greet
|
37
|
+
client.uncast
|
38
|
+
assert_raises(NoMethodError){ client.greet }
|
39
|
+
end
|
40
|
+
|
41
|
+
it "maintains any previously added delegates" do
|
42
|
+
client.cast_as(TestPerson::Verbose)
|
43
|
+
assert_equal 'one,two', client.verbose('one', 'two')
|
44
|
+
client.uncast
|
45
|
+
assert_raises(NoMethodError){ client.verbose('one', 'two') }
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns the object for further operation" do
|
49
|
+
jim = test_person.extend(Casting::Client, Casting::MissingMethodClient)
|
50
|
+
|
51
|
+
assert_equal 'name from TestPerson', jim.uncast.name
|
52
|
+
end
|
53
|
+
end
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: casting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jim Gay
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-29 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: redcard
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,15 +20,14 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 1.1.0
|
30
|
-
description:
|
31
|
-
'self' to the object receiving a message
|
32
|
-
|
33
|
-
|
27
|
+
description: |-
|
28
|
+
Casting assists in method delegation which preserves the binding of 'self' to the object receiving a message.
|
29
|
+
|
30
|
+
This allows you to define behavior and apply it to an object temporarily without extending the object's super class structure.
|
34
31
|
email:
|
35
32
|
- jim@saturnflyer.com
|
36
33
|
executables: []
|
@@ -39,37 +36,46 @@ extra_rdoc_files: []
|
|
39
36
|
files:
|
40
37
|
- lib/casting.rb
|
41
38
|
- lib/casting/version.rb
|
39
|
+
- lib/casting/delegation.rb
|
40
|
+
- lib/casting/missing_method_client.rb
|
41
|
+
- lib/casting/prepared_delegation.rb
|
42
|
+
- lib/casting/client.rb
|
42
43
|
- test/test_helper.rb
|
43
|
-
- test/casting_test.rb
|
44
44
|
- test/casting_19_test.rb
|
45
45
|
- test/casting_20_test.rb
|
46
|
+
- test/casting_test.rb
|
47
|
+
- test/client_test.rb
|
48
|
+
- test/delegation_test.rb
|
49
|
+
- test/missing_method_client_test.rb
|
46
50
|
homepage: http://github.com/saturnflyer/casting
|
47
|
-
licenses:
|
51
|
+
licenses:
|
52
|
+
- MIT
|
53
|
+
metadata: {}
|
48
54
|
post_install_message:
|
49
55
|
rdoc_options: []
|
50
56
|
require_paths:
|
51
57
|
- lib
|
52
58
|
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
-
none: false
|
54
59
|
requirements:
|
55
|
-
- -
|
60
|
+
- - '>='
|
56
61
|
- !ruby/object:Gem::Version
|
57
62
|
version: '0'
|
58
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
64
|
requirements:
|
61
|
-
- -
|
65
|
+
- - '>='
|
62
66
|
- !ruby/object:Gem::Version
|
63
67
|
version: '0'
|
64
68
|
requirements: []
|
65
69
|
rubyforge_project:
|
66
|
-
rubygems_version:
|
70
|
+
rubygems_version: 2.0.0
|
67
71
|
signing_key:
|
68
|
-
specification_version:
|
72
|
+
specification_version: 4
|
69
73
|
summary: Proper method delegation.
|
70
74
|
test_files:
|
71
75
|
- test/test_helper.rb
|
72
|
-
- test/casting_test.rb
|
73
76
|
- test/casting_19_test.rb
|
74
77
|
- test/casting_20_test.rb
|
75
|
-
|
78
|
+
- test/casting_test.rb
|
79
|
+
- test/client_test.rb
|
80
|
+
- test/delegation_test.rb
|
81
|
+
- test/missing_method_client_test.rb
|