casting 0.7.2 → 1.0.0
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 +5 -5
- data/LICENSE +1 -1
- data/README.md +13 -2
- data/lib/casting/client.rb +4 -4
- data/lib/casting/context.rb +26 -15
- data/lib/casting/delegation.rb +87 -15
- data/lib/casting/missing_method_client.rb +6 -9
- data/lib/casting/missing_method_client_class.rb +1 -1
- data/lib/casting/null.rb +4 -4
- data/lib/casting/super_delegate.rb +24 -18
- data/lib/casting/version.rb +2 -2
- data/lib/casting.rb +3 -0
- data/test/casting_test.rb +19 -0
- data/test/client_test.rb +1 -1
- data/test/context_test.rb +80 -0
- data/test/delegation_test.rb +143 -9
- data/test/null_module_test.rb +11 -0
- data/test/super_test.rb +53 -4
- data/test/test_helper.rb +24 -3
- metadata +9 -13
- data/lib/casting/prepared_delegation.rb +0 -79
- data/test/casting_19_test.rb +0 -54
- data/test/casting_20_test.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a7d5101d4c7109e86710609589a9f7dcd4d9d5452e7a452fa29349297325d9a7
|
4
|
+
data.tar.gz: 5854e95575b52af1b6d912a5aa3dc18101faa109d9bea387dba59b6bd50b9df7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b394e9b29860bc90654751bc36296ddf5d67598bddf7a3bcec570d507a31ed62674ddce23cfa25a7a6f8d202664c131fec735f3bd4de2074940f88f3860a9f3
|
7
|
+
data.tar.gz: 3e02eb89ad5894b7866569e21aa2efb00e5d00ce9a1d74d1d0865bf7b67303e9a3ddf82333044411a4f1f4f54ff3e0296b42cddaffba1c978609c8f335db2ce7
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# Casting
|
2
2
|
|
3
|
-
[](https://travis-ci.org/saturnflyer/casting)
|
4
3
|
[](https://codeclimate.com/github/saturnflyer/casting)
|
5
4
|
[](https://codeclimate.com/github/saturnflyer/casting/coverage)
|
6
5
|
[](http://badge.fury.io/rb/casting)
|
@@ -72,6 +71,12 @@ You may also delegate methods without an explicit attendant instance, but provid
|
|
72
71
|
a module containing the behavior you need to use:
|
73
72
|
|
74
73
|
```ruby
|
74
|
+
module GreetingModule
|
75
|
+
def hello_world
|
76
|
+
"hello world"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
75
80
|
actor.delegate(:hello_world, GreetingModule)
|
76
81
|
# or
|
77
82
|
actor.delegation(:hello_world).to(GreetingModule).call
|
@@ -98,6 +103,12 @@ Casting also provides an option to temporarily apply behaviors to an object.
|
|
98
103
|
Once your class or object is a `Casting::Client` you may send the `delegate_missing_methods` message to it and your object will use `method_missing` to delegate methods to a stored attendant.
|
99
104
|
|
100
105
|
```ruby
|
106
|
+
class Actor
|
107
|
+
include Casting::Client
|
108
|
+
delegate_missing_methods
|
109
|
+
end
|
110
|
+
actor = Actor.new
|
111
|
+
|
101
112
|
actor.hello_world #=> NoMethodError
|
102
113
|
|
103
114
|
Casting.delegating(actor => GreetingModule) do
|
@@ -109,7 +120,7 @@ actor.hello_world #=> NoMethodError
|
|
109
120
|
|
110
121
|
The use of `method_missing` is opt-in. If you don't want that mucking up your method calls, just don't tell it to `delegate_missing_methods`.
|
111
122
|
|
112
|
-
Before the block is run in `Casting.delegating`, a collection of delegate objects is set
|
123
|
+
Before the block is run in `Casting.delegating`, a collection of delegate objects is set in the current Thread for the provided attendant. Then the block yields, and an `ensure` block cleans up the stored attendant.
|
113
124
|
|
114
125
|
This allows you to nest your `delegating` blocks as well:
|
115
126
|
|
data/lib/casting/client.rb
CHANGED
@@ -22,12 +22,12 @@ module Casting
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def delegation(delegated_method_name)
|
25
|
-
Casting::Delegation.
|
25
|
+
Casting::Delegation.prepare(delegated_method_name, self)
|
26
26
|
end
|
27
27
|
|
28
|
-
def cast(delegated_method_name, attendant,
|
28
|
+
def cast(delegated_method_name, attendant, ...)
|
29
29
|
validate_attendant(attendant)
|
30
|
-
delegation(delegated_method_name).to(attendant).
|
30
|
+
delegation(delegated_method_name).to(attendant).call(...)
|
31
31
|
end
|
32
32
|
|
33
33
|
def delegate_missing_methods(*which)
|
@@ -63,4 +63,4 @@ module Casting
|
|
63
63
|
base.send(:extend, ::Casting::MissingMethodClientClass)
|
64
64
|
end
|
65
65
|
end
|
66
|
-
end
|
66
|
+
end
|
data/lib/casting/context.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
#
|
8
8
|
# class SomeContext
|
9
9
|
# using Casting::Context
|
10
|
-
#
|
10
|
+
# extend Casting::Context
|
11
11
|
#
|
12
12
|
# initialize(:some, :thing)
|
13
13
|
# # doing that defines your constructor but would cause it too look for
|
@@ -18,7 +18,6 @@
|
|
18
18
|
# # if you want different module names (why would you?) then you'd need
|
19
19
|
# # to do all this:
|
20
20
|
# def initialize(some, thing)
|
21
|
-
# @assignments = []
|
22
21
|
# assign [some, SomeRole], [thing, OtherRole]
|
23
22
|
# Thread.current[:context] = self
|
24
23
|
# end
|
@@ -28,9 +27,6 @@
|
|
28
27
|
# module OtherRole; end
|
29
28
|
# end
|
30
29
|
#
|
31
|
-
# In order to use this the objects sent into the context contstructor *must*
|
32
|
-
# `include Casting::Client` so that the `cast` method is available to them
|
33
|
-
#
|
34
30
|
module Casting
|
35
31
|
module Context
|
36
32
|
|
@@ -38,10 +34,16 @@ module Casting
|
|
38
34
|
base.send(:include, InstanceMethods)
|
39
35
|
end
|
40
36
|
|
41
|
-
def initialize(*setup_args)
|
37
|
+
def initialize(*setup_args, &block)
|
42
38
|
attr_reader(*setup_args)
|
43
39
|
private(*setup_args)
|
44
40
|
|
41
|
+
if block
|
42
|
+
define_method(:__custom_initialize, &block)
|
43
|
+
else
|
44
|
+
define_method(:__custom_initialize) do; end
|
45
|
+
end
|
46
|
+
|
45
47
|
mod = Module.new
|
46
48
|
line = __LINE__; string = %<
|
47
49
|
def initialize(#{setup_args.map{|name| "#{name}:" }.join(',')})
|
@@ -49,6 +51,7 @@ module Casting
|
|
49
51
|
#{setup_args.map do |name|
|
50
52
|
["assign(",name,", '",name,"')"].join
|
51
53
|
end.join("\n")}
|
54
|
+
__custom_initialize
|
52
55
|
Thread.current[:context] = self
|
53
56
|
end
|
54
57
|
attr_reader :assignments
|
@@ -62,7 +65,11 @@ module Casting
|
|
62
65
|
def context
|
63
66
|
self
|
64
67
|
end
|
65
|
-
|
68
|
+
|
69
|
+
def assignments
|
70
|
+
@assignments ||= []
|
71
|
+
end
|
72
|
+
|
66
73
|
# Keep track of objects and their behaviors
|
67
74
|
def assign(object, role_name)
|
68
75
|
instance_variable_set("@#{role_name}", object)
|
@@ -74,15 +81,19 @@ module Casting
|
|
74
81
|
end
|
75
82
|
|
76
83
|
# Execute the behavior from the role on the specifed object
|
77
|
-
def dispatch(object, method_name,
|
78
|
-
object.cast
|
84
|
+
def dispatch(object, method_name, ...)
|
85
|
+
if object.respond_to?(:cast)
|
86
|
+
object.cast(method_name, context.role_implementing(object, method_name), ...)
|
87
|
+
else
|
88
|
+
Casting::Delegation.prepare(method_name, object).to(role_implementing(object, method_name)).with(...).call
|
89
|
+
end
|
79
90
|
end
|
80
|
-
|
91
|
+
|
81
92
|
# Find the first assigned role which implements a response for the given method name
|
82
93
|
def role_implementing(object, method_name)
|
83
94
|
assigned_roles(object).find{|role| role.method_defined?(method_name) } || raise(NoMethodError, "unknown method '#{method_name}' expected for #{object}")
|
84
95
|
end
|
85
|
-
|
96
|
+
|
86
97
|
# Get the roles for the given object
|
87
98
|
def assigned_roles(object)
|
88
99
|
assignments.select{|pair|
|
@@ -96,7 +107,7 @@ module Casting
|
|
96
107
|
role_name = name.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }
|
97
108
|
self.class.const_get(role_name)
|
98
109
|
rescue NameError
|
99
|
-
Module
|
110
|
+
Module.new
|
100
111
|
end
|
101
112
|
end
|
102
113
|
|
@@ -115,11 +126,11 @@ module Casting
|
|
115
126
|
end
|
116
127
|
|
117
128
|
# Execute the named method on the object plaing the name role
|
118
|
-
def tell(role_name, method_name,
|
129
|
+
def tell(role_name, method_name, ...)
|
119
130
|
if context == self || context.contains?(self)
|
120
|
-
context.dispatch(role(role_name), method_name,
|
131
|
+
context.dispatch(role(role_name), method_name, ...)
|
121
132
|
end
|
122
133
|
end
|
123
134
|
end
|
124
135
|
end
|
125
|
-
end
|
136
|
+
end
|
data/lib/casting/delegation.rb
CHANGED
@@ -1,32 +1,104 @@
|
|
1
|
-
require 'casting/prepared_delegation'
|
2
|
-
|
3
1
|
module Casting
|
4
|
-
class Delegation
|
5
2
|
|
6
|
-
|
7
|
-
|
3
|
+
class MissingAttendant < StandardError
|
4
|
+
def message
|
5
|
+
"You must set your attendant object using `to'."
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class InvalidAttendant < StandardError; end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
class Delegation
|
12
|
+
|
13
|
+
def self.prepare(delegated_method_name, client, &block)
|
14
|
+
new(delegated_method_name: delegated_method_name, client: client, &block)
|
11
15
|
end
|
12
16
|
|
13
|
-
|
14
|
-
|
17
|
+
attr_accessor :client, :delegated_method_name, :attendant, :arguments, :block
|
18
|
+
private :block
|
19
|
+
|
20
|
+
def initialize(**settings, &block)
|
21
|
+
@delegated_method_name = settings[:delegated_method_name]
|
22
|
+
@client = settings[:client]
|
23
|
+
@attendant = settings[:attendant]
|
24
|
+
@arguments = settings[:arguments]
|
25
|
+
@keyword_arguments = settings[:keyword_arguments]
|
26
|
+
@block = block
|
15
27
|
end
|
16
28
|
|
17
29
|
def to(object_or_module)
|
18
|
-
|
30
|
+
@attendant = object_or_module
|
31
|
+
begin
|
32
|
+
bound_method
|
33
|
+
rescue TypeError
|
34
|
+
@attendant = method_module || raise
|
35
|
+
end
|
19
36
|
self
|
20
37
|
end
|
21
38
|
|
22
|
-
def with(*args, &block)
|
23
|
-
|
39
|
+
def with(*args, **kwargs, &block)
|
40
|
+
@arguments = args
|
41
|
+
@keyword_arguments = kwargs
|
42
|
+
@block = block
|
24
43
|
self
|
25
44
|
end
|
26
45
|
|
27
|
-
def call(*args)
|
28
|
-
|
46
|
+
def call(*args, **kwargs, &block)
|
47
|
+
raise MissingAttendant.new unless attendant
|
48
|
+
|
49
|
+
call_args = if args && !args.empty?
|
50
|
+
args
|
51
|
+
elsif @arguments && !@arguments.empty?
|
52
|
+
@arguments
|
53
|
+
end
|
54
|
+
call_kwargs = if kwargs && !kwargs.empty?
|
55
|
+
kwargs
|
56
|
+
elsif @keyword_arguments && !@keyword_arguments.empty?
|
57
|
+
@keyword_arguments
|
58
|
+
end
|
59
|
+
|
60
|
+
call_block = block || @block
|
61
|
+
if call_args
|
62
|
+
if call_kwargs
|
63
|
+
bound_method.call(*call_args, **call_kwargs, &call_block)
|
64
|
+
else
|
65
|
+
bound_method.call(*call_args, &call_block)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
if call_kwargs
|
69
|
+
bound_method.call(**call_kwargs, &call_block)
|
70
|
+
else
|
71
|
+
bound_method.call(&call_block)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def bound_method
|
79
|
+
begin
|
80
|
+
delegated_method.bind(client)
|
81
|
+
rescue TypeError
|
82
|
+
raise TypeError.new("`to' argument must be a module or an object with #{delegated_method_name} defined in a module")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_module
|
87
|
+
mod = delegated_method.owner
|
88
|
+
unless mod.is_a?(Class)
|
89
|
+
mod
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def delegated_method
|
94
|
+
if Module === attendant
|
95
|
+
attendant.instance_method(delegated_method_name)
|
96
|
+
else
|
97
|
+
attendant.method(delegated_method_name).owner.instance_method(delegated_method_name)
|
98
|
+
end
|
99
|
+
rescue NameError => e
|
100
|
+
raise InvalidAttendant.new(e.message)
|
29
101
|
end
|
30
102
|
|
31
103
|
end
|
32
|
-
end
|
104
|
+
end
|
@@ -47,18 +47,15 @@ module Casting
|
|
47
47
|
private
|
48
48
|
|
49
49
|
def __delegates__
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
else
|
54
|
-
@__delegates__ = []
|
55
|
-
end
|
50
|
+
Thread.current[:instance_delegates] ||= {}
|
51
|
+
Thread.current[:instance_delegates][object_id] ||= []
|
52
|
+
Thread.current[:instance_delegates][object_id]
|
56
53
|
end
|
57
54
|
|
58
|
-
def method_missing(meth,
|
55
|
+
def method_missing(meth, ...)
|
59
56
|
attendant = method_delegate(meth)
|
60
57
|
if !!attendant
|
61
|
-
|
58
|
+
cast(meth, attendant, ...)
|
62
59
|
else
|
63
60
|
super
|
64
61
|
end
|
@@ -105,4 +102,4 @@ module Casting
|
|
105
102
|
end
|
106
103
|
end
|
107
104
|
end
|
108
|
-
end
|
105
|
+
end
|
data/lib/casting/null.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module Casting
|
2
2
|
module Null
|
3
|
-
def self.instance_method(_)
|
3
|
+
def self.instance_method(*_)
|
4
4
|
Empty.instance_method(:null)
|
5
5
|
end
|
6
|
-
def self.method_defined?(_)
|
6
|
+
def self.method_defined?(*_)
|
7
7
|
true
|
8
8
|
end
|
9
9
|
end
|
10
10
|
module Blank
|
11
|
-
def self.instance_method(_)
|
11
|
+
def self.instance_method(*_)
|
12
12
|
Empty.instance_method(:blank)
|
13
13
|
end
|
14
|
-
def self.method_defined?(_)
|
14
|
+
def self.method_defined?(*_)
|
15
15
|
true
|
16
16
|
end
|
17
17
|
end
|
@@ -28,17 +28,12 @@ module Casting
|
|
28
28
|
# some_object.cast_as(Greeter, FormalGreeter)
|
29
29
|
# some_object.greet #=> 'Hello, how do you do?'
|
30
30
|
#
|
31
|
-
def super_delegate(*args, &block)
|
32
|
-
method_name = name_of_calling_method(
|
33
|
-
owner =
|
34
|
-
|
35
|
-
super_delegate_method = unbound_method_from_next_delegate(method_name, owner)
|
31
|
+
def super_delegate(mod = :none, *args, **kwargs, &block)
|
32
|
+
method_name = name_of_calling_method(caller_locations)
|
33
|
+
owner = (mod unless mod == :none) || method_delegate(method_name)
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
else
|
40
|
-
super_delegate_method.bind(self).call(*args, &block)
|
41
|
-
end
|
35
|
+
super_delegate_method = unbound_method_from_next_delegate(method_name, owner)
|
36
|
+
super_delegate_method.bind(self).call(*args, **kwargs, &block)
|
42
37
|
rescue NameError
|
43
38
|
raise NoMethodError.new("super_delegate: no delegate method `#{method_name}' for #{self.inspect} from #{owner}")
|
44
39
|
end
|
@@ -49,20 +44,31 @@ module Casting
|
|
49
44
|
|
50
45
|
def method_delegate_skipping(meth, skipped)
|
51
46
|
skipped_index = __delegates__.index(skipped)
|
52
|
-
__delegates__.find{|attendant|
|
53
|
-
attendant_methods(attendant).include?(meth)
|
54
|
-
skipped_index < __delegates__.index(attendant)
|
47
|
+
__delegates__[(skipped_index + 1)..__delegates__.length].find{|attendant|
|
48
|
+
attendant_methods(attendant).include?(meth)
|
55
49
|
}
|
56
50
|
end
|
57
|
-
|
58
|
-
def
|
51
|
+
|
52
|
+
def calling_location(call_stack)
|
59
53
|
call_stack.reject{|line|
|
60
|
-
line.to_s
|
61
|
-
}.first
|
54
|
+
line.to_s.match? Regexp.union(casting_library_matcher, gem_home_matcher, debugging_matcher)
|
55
|
+
}.first
|
56
|
+
end
|
57
|
+
|
58
|
+
def name_of_calling_method(call_stack)
|
59
|
+
calling_location(call_stack).label.to_sym
|
62
60
|
end
|
63
61
|
|
64
62
|
def casting_library_matcher
|
65
63
|
Regexp.new(Dir.pwd.to_s + '/lib')
|
66
64
|
end
|
65
|
+
|
66
|
+
def gem_home_matcher
|
67
|
+
Regexp.new(ENV['GEM_HOME'])
|
68
|
+
end
|
69
|
+
|
70
|
+
def debugging_matcher
|
71
|
+
Regexp.new('internal:trace_point')
|
72
|
+
end
|
67
73
|
end
|
68
|
-
end
|
74
|
+
end
|
data/lib/casting/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Casting
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
2
|
+
VERSION = '1.0.0'
|
3
|
+
end
|
data/lib/casting.rb
CHANGED
data/test/casting_test.rb
CHANGED
@@ -1,6 +1,25 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
describe Casting, '.delegating' do
|
4
|
+
it 'delegates missing methods to object delegates' do
|
5
|
+
client = test_person
|
6
|
+
client.extend(Casting::Client)
|
7
|
+
client.delegate_missing_methods
|
8
|
+
|
9
|
+
attendant = test_person
|
10
|
+
attendant.extend(TestPerson::Greeter)
|
11
|
+
|
12
|
+
assert_raises(NoMethodError){
|
13
|
+
client.greet
|
14
|
+
}
|
15
|
+
Casting.delegating(client => attendant) do
|
16
|
+
assert_equal 'hello', client.greet
|
17
|
+
end
|
18
|
+
assert_raises(NoMethodError){
|
19
|
+
client.greet
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
4
23
|
it 'delegates missing methods for the objects inside the block' do
|
5
24
|
client = BlockTestPerson.new('Jim')
|
6
25
|
verbose_client = BlockTestPerson.new('Amy')
|
data/test/client_test.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestContext
|
4
|
+
using Casting::Context
|
5
|
+
extend Casting::Context
|
6
|
+
|
7
|
+
initialize :admin, :user
|
8
|
+
|
9
|
+
def approve
|
10
|
+
tell :admin, :say, 'I approve'
|
11
|
+
end
|
12
|
+
|
13
|
+
def approve_with_keyword
|
14
|
+
tell :admin, :keyword_say, what: 'I approve'
|
15
|
+
end
|
16
|
+
|
17
|
+
def user_approve
|
18
|
+
tell :user, :approve
|
19
|
+
end
|
20
|
+
|
21
|
+
module Admin
|
22
|
+
def say(what)
|
23
|
+
what
|
24
|
+
end
|
25
|
+
|
26
|
+
def keyword_say(what:)
|
27
|
+
what
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module User
|
32
|
+
def approve
|
33
|
+
'Yay!'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class MissingModuleContext
|
39
|
+
using Casting::Context
|
40
|
+
extend Casting::Context
|
41
|
+
|
42
|
+
initialize :admin, :user
|
43
|
+
|
44
|
+
def run
|
45
|
+
tell :admin, :go
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe Casting::Context do
|
50
|
+
it 'applies module methods to Casting::Client objects' do
|
51
|
+
admin = casting_person
|
52
|
+
user = casting_person
|
53
|
+
|
54
|
+
context = TestContext.new admin: admin, user: user
|
55
|
+
|
56
|
+
expect(context.approve).must_equal ('I approve')
|
57
|
+
expect(context.approve_with_keyword).must_equal ('I approve')
|
58
|
+
expect(context.user_approve).must_equal ('Yay!')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'applies module methods to any object' do
|
62
|
+
admin = Object.new
|
63
|
+
user = 1
|
64
|
+
|
65
|
+
context = TestContext.new admin: admin, user: user
|
66
|
+
|
67
|
+
expect(context.approve).must_equal ('I approve')
|
68
|
+
expect(context.user_approve).must_equal ('Yay!')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'handles missing modules and raises missing method error' do
|
72
|
+
admin = TestPerson.new
|
73
|
+
user = TestPerson.new
|
74
|
+
|
75
|
+
context = MissingModuleContext.new admin: admin, user: user
|
76
|
+
|
77
|
+
err = expect{ context.run }.must_raise(NoMethodError)
|
78
|
+
expect(err.message).must_match(/unknown method 'go'/)
|
79
|
+
end
|
80
|
+
end
|
data/test/delegation_test.rb
CHANGED
@@ -3,11 +3,11 @@ require 'test_helper'
|
|
3
3
|
describe Casting::Delegation do
|
4
4
|
|
5
5
|
it 'initializes with method name and object' do
|
6
|
-
assert Casting::Delegation.
|
6
|
+
assert Casting::Delegation.prepare('some_method', Object.new)
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'raises an error when calling without an attendant object' do
|
10
|
-
delegation = Casting::Delegation.
|
10
|
+
delegation = Casting::Delegation.prepare('some_method', Object.new)
|
11
11
|
begin
|
12
12
|
delegation.call
|
13
13
|
rescue StandardError => e
|
@@ -17,7 +17,14 @@ describe Casting::Delegation do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'raises an error when setting an invalid attendant type' do
|
20
|
-
delegation = Casting::Delegation.
|
20
|
+
delegation = Casting::Delegation.prepare('some_method', TestPerson.new)
|
21
|
+
assert_raises(Casting::InvalidAttendant){
|
22
|
+
delegation.to(Unrelated.new)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'raises an error when setting a class as the attendant' do
|
27
|
+
delegation = Casting::Delegation.prepare('some_method', TestPerson)
|
21
28
|
assert_raises(Casting::InvalidAttendant){
|
22
29
|
delegation.to(Unrelated.new)
|
23
30
|
}
|
@@ -27,20 +34,36 @@ describe Casting::Delegation do
|
|
27
34
|
attendant = test_person
|
28
35
|
client = SubTestPerson.new
|
29
36
|
|
30
|
-
delegation = Casting::Delegation.
|
37
|
+
delegation = Casting::Delegation.prepare('name', client)
|
31
38
|
assert delegation.to(attendant)
|
32
39
|
end
|
33
40
|
|
34
41
|
it 'delegates when given a module' do
|
35
42
|
client = test_person
|
36
|
-
delegation = Casting::Delegation.
|
43
|
+
delegation = Casting::Delegation.prepare('greet', client).to(TestPerson::Greeter)
|
37
44
|
assert_equal 'hello', delegation.call
|
38
45
|
end
|
39
46
|
|
40
47
|
it 'does not delegate when given a class' do
|
41
48
|
client = test_person
|
49
|
+
err = expect{
|
50
|
+
Casting::Delegation.prepare('class_defined', client).to(Unrelated)
|
51
|
+
}.must_raise(TypeError)
|
52
|
+
expect(err.message).must_match(/ argument must be a module or an object with/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'finds the module defining a method and uses it to delegate' do
|
56
|
+
client = test_person
|
57
|
+
attendant = Unrelated.new
|
58
|
+
delegation = Casting::Delegation.prepare('unrelated', client).to(attendant)
|
59
|
+
assert_equal attendant.unrelated, delegation.call
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'does not delegate to methods defined in classes' do
|
63
|
+
client = test_person
|
64
|
+
attendant = Unrelated.new
|
42
65
|
assert_raises(TypeError){
|
43
|
-
Casting::Delegation.
|
66
|
+
Casting::Delegation.prepare('class_defined', client).to(attendant)
|
44
67
|
}
|
45
68
|
end
|
46
69
|
|
@@ -48,17 +71,128 @@ describe Casting::Delegation do
|
|
48
71
|
client = test_person
|
49
72
|
attendant = TestPerson::Verbose
|
50
73
|
|
51
|
-
delegation = Casting::Delegation.
|
74
|
+
delegation = Casting::Delegation.prepare('verbose', client).to(attendant)
|
52
75
|
|
53
76
|
assert_equal 'hello,goodbye', delegation.with('hello', 'goodbye').call
|
54
77
|
end
|
55
78
|
|
79
|
+
it 'assigns keyword arguments to the delegated method using with' do
|
80
|
+
client = test_person
|
81
|
+
attendant = TestPerson::Verbose
|
82
|
+
|
83
|
+
delegation = Casting::Delegation.prepare('verbose_keywords', client).to(attendant)
|
84
|
+
|
85
|
+
assert_equal 'hello,goodbye', delegation.with(key: 'hello', word: 'goodbye').call
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'assigns regular and keyword arguments to the delegated method using with' do
|
89
|
+
client = test_person
|
90
|
+
attendant = TestPerson::Verbose
|
91
|
+
|
92
|
+
delegation = Casting::Delegation.prepare('verbose_multi_args', client).to(attendant)
|
93
|
+
|
94
|
+
assert_equal('hello,goodbye,keys,words,block!', delegation.with('hello', 'goodbye', key: 'keys', word: 'words') do
|
95
|
+
"block!"
|
96
|
+
end.call)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'handles flexible arguments to the delegated method using with' do
|
100
|
+
client = test_person
|
101
|
+
attendant = TestPerson::Verbose
|
102
|
+
|
103
|
+
delegation = Casting::Delegation.prepare('verbose_flex', client).to(attendant)
|
104
|
+
|
105
|
+
assert_equal('hello,key:keys,word:words,block!', delegation.with('hello', key: 'keys', word: 'words') do
|
106
|
+
"block!"
|
107
|
+
end.call)
|
108
|
+
end
|
109
|
+
|
56
110
|
it 'prefers `call` arguments over `with`' do
|
57
111
|
client = test_person
|
58
112
|
attendant = TestPerson::Verbose
|
59
113
|
|
60
|
-
delegation = Casting::Delegation.
|
114
|
+
delegation = Casting::Delegation.prepare('verbose', client).to(attendant)
|
61
115
|
|
62
116
|
assert_equal 'call,args', delegation.with('hello', 'goodbye').call('call','args')
|
63
117
|
end
|
64
|
-
|
118
|
+
|
119
|
+
it 'prefers "call" keyword arguments over "with"' do
|
120
|
+
client = test_person
|
121
|
+
attendant = TestPerson::Verbose
|
122
|
+
|
123
|
+
delegation = Casting::Delegation.prepare('verbose_keywords', client).to(attendant)
|
124
|
+
|
125
|
+
assert_equal 'call,args', delegation.with(key: 'hello', word: 'goodbye').call(key: 'call', word: 'args')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'prefers "call" regular and keyword arguments over "with"' do
|
129
|
+
client = test_person
|
130
|
+
attendant = TestPerson::Verbose
|
131
|
+
|
132
|
+
delegation = Casting::Delegation.prepare('verbose_multi_args', client).to(attendant)
|
133
|
+
|
134
|
+
assert_equal 'hello,goodbye,call,args', delegation.with('this', 'that', key: 'something', word: 'else').call('hello', 'goodbye', key: 'call', word: 'args')
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'prefers "call" block arguments over "with"' do
|
138
|
+
client = test_person
|
139
|
+
attendant = TestPerson::Verbose
|
140
|
+
|
141
|
+
delegation = Casting::Delegation.prepare('verbose_multi_args', client).to(attendant)
|
142
|
+
|
143
|
+
prepared = delegation.with('this', 'that', key: 'something', word: 'else') { "prepared block!" }
|
144
|
+
|
145
|
+
assert_equal('this,that,something,else,call block!', prepared.call{ "call block!" })
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'prefers "call" keyword arguments and block over "with"' do
|
149
|
+
client = test_person
|
150
|
+
attendant = TestPerson::Verbose
|
151
|
+
|
152
|
+
delegation = Casting::Delegation.prepare('verbose_flex', client).to(attendant)
|
153
|
+
|
154
|
+
prepared = delegation.with(key: 'something', word: 'else') { "prepared block!" }
|
155
|
+
|
156
|
+
assert_equal('key:call_key,word:call_word,call block!', prepared.call(key: 'call_key', word: 'call_word'){ "call block!" })
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'prefers "call" and block over "with"' do
|
160
|
+
client = test_person
|
161
|
+
attendant = TestPerson::Verbose
|
162
|
+
|
163
|
+
delegation = Casting::Delegation.prepare('verbose_flex', client).to(attendant)
|
164
|
+
|
165
|
+
prepared = delegation.with { "prepared block!" }
|
166
|
+
|
167
|
+
assert_equal('call block!', prepared.call { "call block!" })
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'calls a method defined on another object of the same type' do
|
171
|
+
client = test_person
|
172
|
+
attendant = test_person
|
173
|
+
attendant.extend(TestPerson::Greeter)
|
174
|
+
delegation = Casting::Delegation.prepare('greet', client).to(attendant)
|
175
|
+
assert_equal 'hello', delegation.call
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'passes arguments to a delegated method' do
|
179
|
+
client = test_person
|
180
|
+
attendant = test_person
|
181
|
+
attendant.extend(TestPerson::Verbose)
|
182
|
+
delegation = Casting::Delegation.prepare('verbose', client).to(attendant).with('arg1','arg2')
|
183
|
+
assert_equal 'arg1,arg2', delegation.call
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'delegates when given a module' do
|
187
|
+
client = test_person
|
188
|
+
delegation = Casting::Delegation.prepare('greet', client).to(TestPerson::Greeter)
|
189
|
+
assert_equal 'hello', delegation.call
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'does not delegate when given a class' do
|
193
|
+
client = test_person
|
194
|
+
assert_raises(TypeError){
|
195
|
+
Casting::Delegation.prepare('class_defined', client).to(Unrelated)
|
196
|
+
}
|
197
|
+
end
|
198
|
+
end
|
data/test/null_module_test.rb
CHANGED
@@ -21,6 +21,17 @@ describe Casting::Blank do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe "making null objects" do
|
24
|
+
it "answers to missing methods" do
|
25
|
+
client = TestPerson.new
|
26
|
+
client.extend(Casting::Client)
|
27
|
+
client.delegate_missing_methods
|
28
|
+
attendant = Casting::Null
|
29
|
+
|
30
|
+
assert_respond_to client.cast_as(attendant), 'xyz'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "making blank objects" do
|
24
35
|
it "answers to missing methods" do
|
25
36
|
client = TestPerson.new
|
26
37
|
client.extend(Casting::Client)
|
data/test/super_test.rb
CHANGED
@@ -4,19 +4,40 @@ module AnyWay
|
|
4
4
|
def which_way
|
5
5
|
"any way"
|
6
6
|
end
|
7
|
+
def way_with_args(one, two, &block)
|
8
|
+
[one, two, block&.call].compact.inspect
|
9
|
+
end
|
10
|
+
def way_with_keyword_args(one:, two:, &block)
|
11
|
+
[one, two, block&.call].compact.inspect
|
12
|
+
end
|
7
13
|
end
|
8
14
|
|
9
15
|
module ThisWay
|
10
16
|
include Casting::SuperDelegate
|
11
17
|
def which_way
|
12
|
-
"this way or #{super_delegate
|
18
|
+
"this way or #{super_delegate}"
|
19
|
+
end
|
20
|
+
def way_with_args(one, two, &block)
|
21
|
+
[one, two, block&.call].compact.inspect
|
22
|
+
end
|
23
|
+
def way_with_keyword_args(one:, two:, &block)
|
24
|
+
[one, two, block&.call].compact.inspect
|
25
|
+
end
|
26
|
+
def no_super
|
27
|
+
super_delegate
|
13
28
|
end
|
14
29
|
end
|
15
30
|
|
16
31
|
module ThatWay
|
17
32
|
include Casting::SuperDelegate
|
18
33
|
def which_way
|
19
|
-
"#{ super_delegate } and that way!"
|
34
|
+
"#{ super_delegate(ThatWay) } and that way!"
|
35
|
+
end
|
36
|
+
def way_with_args(one, two, &block)
|
37
|
+
super_delegate(one, two, block&.call).compact
|
38
|
+
end
|
39
|
+
def way_with_keyword_args(one:, two:, &block)
|
40
|
+
[one, two, block&.call].compact.inspect
|
20
41
|
end
|
21
42
|
end
|
22
43
|
|
@@ -24,8 +45,36 @@ describe Casting, 'modules using delegate_super' do
|
|
24
45
|
it 'call the method from the next delegate with the same arguments' do
|
25
46
|
client = TestPerson.new.extend(Casting::Client)
|
26
47
|
client.delegate_missing_methods
|
27
|
-
client.cast_as(AnyWay,
|
48
|
+
client.cast_as(AnyWay, ThatWay, ThisWay)
|
28
49
|
|
29
50
|
assert_equal 'this way or any way and that way!', client.which_way
|
30
51
|
end
|
31
|
-
|
52
|
+
|
53
|
+
it 'passes arguments' do
|
54
|
+
client = TestPerson.new.extend(Casting::Client)
|
55
|
+
client.delegate_missing_methods
|
56
|
+
client.cast_as(ThatWay, ThisWay)
|
57
|
+
|
58
|
+
assert_equal %{["first", "second", "block"]}, client.way_with_args('first', 'second'){ 'block' }
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'passes keyword arguments' do
|
62
|
+
client = TestPerson.new.extend(Casting::Client)
|
63
|
+
client.delegate_missing_methods
|
64
|
+
client.cast_as(ThatWay, ThisWay)
|
65
|
+
|
66
|
+
assert_equal %{["first", "second", "block"]}, client.way_with_keyword_args(one: 'first', two: 'second'){ 'block' }
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'raises an error when method is not defined' do
|
70
|
+
client = TestPerson.new.extend(Casting::Client)
|
71
|
+
client.delegate_missing_methods
|
72
|
+
client.cast_as(ThisWay)
|
73
|
+
|
74
|
+
err = expect{
|
75
|
+
client.no_super
|
76
|
+
}.must_raise(NoMethodError)
|
77
|
+
|
78
|
+
expect(err.message).must_match(/super_delegate: no delegate method \`no_super' for \#<TestPerson:\dx[a-z0-9]*> from ThisWay/)
|
79
|
+
end
|
80
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require "
|
2
|
-
|
3
|
-
|
1
|
+
require "simplecov"
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter 'test'
|
4
|
+
end
|
4
5
|
require 'minitest/autorun'
|
5
6
|
require 'casting'
|
6
7
|
|
@@ -31,9 +32,25 @@ class TestPerson
|
|
31
32
|
def verbose(arg1, arg2)
|
32
33
|
[arg1, arg2].join(',')
|
33
34
|
end
|
35
|
+
|
36
|
+
def verbose_keywords(key:, word:)
|
37
|
+
[key, word].join(',')
|
38
|
+
end
|
39
|
+
|
40
|
+
def verbose_multi_args(arg1, arg2, key:, word:, &block)
|
41
|
+
[arg1, arg2, key, word, block&.call].compact.join(',')
|
42
|
+
end
|
43
|
+
|
44
|
+
def verbose_flex(*args, **kwargs, &block)
|
45
|
+
[args, kwargs.map{|k,v| "#{k}:#{v}"}, block&.call].flatten.compact.join(',')
|
46
|
+
end
|
34
47
|
end
|
35
48
|
end
|
36
49
|
|
50
|
+
class TestGreeter
|
51
|
+
include TestPerson::Greeter
|
52
|
+
end
|
53
|
+
|
37
54
|
class SubTestPerson < TestPerson
|
38
55
|
def sub_method
|
39
56
|
'sub'
|
@@ -74,3 +91,7 @@ end
|
|
74
91
|
def test_person
|
75
92
|
TestPerson.new
|
76
93
|
end
|
94
|
+
|
95
|
+
def casting_person
|
96
|
+
test_person.extend(Casting::Client)
|
97
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: casting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Gay
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
Casting assists in method delegation which preserves the binding of 'self' to the object receiving a message.
|
@@ -31,14 +31,12 @@ files:
|
|
31
31
|
- lib/casting/missing_method_client.rb
|
32
32
|
- lib/casting/missing_method_client_class.rb
|
33
33
|
- lib/casting/null.rb
|
34
|
-
- lib/casting/prepared_delegation.rb
|
35
34
|
- lib/casting/super_delegate.rb
|
36
35
|
- lib/casting/version.rb
|
37
|
-
- test/casting_19_test.rb
|
38
|
-
- test/casting_20_test.rb
|
39
36
|
- test/casting_test.rb
|
40
37
|
- test/class_refinement_test.rb
|
41
38
|
- test/client_test.rb
|
39
|
+
- test/context_test.rb
|
42
40
|
- test/delegation_test.rb
|
43
41
|
- test/method_consolidator_test.rb
|
44
42
|
- test/missing_method_client_test.rb
|
@@ -50,7 +48,7 @@ homepage: http://github.com/saturnflyer/casting
|
|
50
48
|
licenses:
|
51
49
|
- MIT
|
52
50
|
metadata: {}
|
53
|
-
post_install_message:
|
51
|
+
post_install_message:
|
54
52
|
rdoc_options: []
|
55
53
|
require_paths:
|
56
54
|
- lib
|
@@ -58,25 +56,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
56
|
requirements:
|
59
57
|
- - ">="
|
60
58
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
59
|
+
version: '2.7'
|
62
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
61
|
requirements:
|
64
62
|
- - ">="
|
65
63
|
- !ruby/object:Gem::Version
|
66
64
|
version: '0'
|
67
65
|
requirements: []
|
68
|
-
|
69
|
-
|
70
|
-
signing_key:
|
66
|
+
rubygems_version: 3.1.6
|
67
|
+
signing_key:
|
71
68
|
specification_version: 4
|
72
69
|
summary: Proper method delegation.
|
73
70
|
test_files:
|
74
71
|
- test/test_helper.rb
|
75
|
-
- test/casting_19_test.rb
|
76
|
-
- test/casting_20_test.rb
|
77
72
|
- test/casting_test.rb
|
78
73
|
- test/class_refinement_test.rb
|
79
74
|
- test/client_test.rb
|
75
|
+
- test/context_test.rb
|
80
76
|
- test/delegation_test.rb
|
81
77
|
- test/method_consolidator_test.rb
|
82
78
|
- test/missing_method_client_test.rb
|
@@ -1,79 +0,0 @@
|
|
1
|
-
module Casting
|
2
|
-
|
3
|
-
class MissingAttendant < StandardError
|
4
|
-
def message
|
5
|
-
"You must set your attendant object using `to'."
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class InvalidAttendant < StandardError; end
|
10
|
-
|
11
|
-
class PreparedDelegation
|
12
|
-
|
13
|
-
attr_accessor :client, :delegated_method_name, :attendant, :arguments, :block
|
14
|
-
private :block
|
15
|
-
|
16
|
-
def initialize(**settings, &block)
|
17
|
-
@delegated_method_name = settings[:delegated_method_name]
|
18
|
-
@client = settings[:client]
|
19
|
-
@attendant = settings[:attendant]
|
20
|
-
@arguments = settings[:arguments]
|
21
|
-
@block = block
|
22
|
-
end
|
23
|
-
|
24
|
-
def to(object_or_module)
|
25
|
-
@attendant = object_or_module
|
26
|
-
begin
|
27
|
-
check_valid_type
|
28
|
-
rescue TypeError
|
29
|
-
@attendant = method_module || raise
|
30
|
-
end
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
def with(*args, &block)
|
35
|
-
@arguments = args
|
36
|
-
@block = block
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def call(*args)
|
41
|
-
@arguments = args unless args.empty?
|
42
|
-
raise MissingAttendant.new unless attendant
|
43
|
-
|
44
|
-
if arguments
|
45
|
-
delegated_method.bind(client).call(*arguments, &block)
|
46
|
-
else
|
47
|
-
delegated_method.bind(client).call
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def check_valid_type
|
54
|
-
begin
|
55
|
-
!client.nil? && delegated_method.bind(client)
|
56
|
-
rescue TypeError
|
57
|
-
raise TypeError.new("`to' argument must be a module or an object with #{delegated_method_name} defined in a module")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def method_module
|
62
|
-
mod = delegated_method.owner
|
63
|
-
unless mod.is_a?(Class)
|
64
|
-
mod
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def delegated_method
|
69
|
-
if Module === attendant
|
70
|
-
attendant.instance_method(delegated_method_name)
|
71
|
-
else
|
72
|
-
attendant.method(delegated_method_name).owner.instance_method(delegated_method_name)
|
73
|
-
end
|
74
|
-
rescue NameError => e
|
75
|
-
raise InvalidAttendant.new(e.message)
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
data/test/casting_19_test.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
describe Casting, '.delegating' do
|
4
|
-
it 'delegates missing methods to object delegates' do
|
5
|
-
client = test_person
|
6
|
-
client.extend(Casting::Client)
|
7
|
-
client.delegate_missing_methods
|
8
|
-
|
9
|
-
attendant = test_person
|
10
|
-
attendant.extend(TestPerson::Greeter)
|
11
|
-
|
12
|
-
assert_raises(NoMethodError){
|
13
|
-
client.greet
|
14
|
-
}
|
15
|
-
Casting.delegating(client => attendant) do
|
16
|
-
assert_equal 'hello', client.greet
|
17
|
-
end
|
18
|
-
assert_raises(NoMethodError){
|
19
|
-
client.greet
|
20
|
-
}
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe Casting::Delegation do
|
25
|
-
|
26
|
-
it 'calls a method defined on another object of the same type' do
|
27
|
-
client = test_person
|
28
|
-
attendant = test_person
|
29
|
-
attendant.extend(TestPerson::Greeter)
|
30
|
-
delegation = Casting::Delegation.new('greet', client).to(attendant)
|
31
|
-
assert_equal 'hello', delegation.call
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'passes arguments to a delegated method' do
|
35
|
-
client = test_person
|
36
|
-
attendant = test_person
|
37
|
-
attendant.extend(TestPerson::Verbose)
|
38
|
-
delegation = Casting::Delegation.new('verbose', client).to(attendant).with('arg1','arg2')
|
39
|
-
assert_equal 'arg1,arg2', delegation.call
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'delegates when given a module' do
|
43
|
-
client = test_person
|
44
|
-
delegation = Casting::Delegation.new('greet', client).to(TestPerson::Greeter)
|
45
|
-
assert_equal 'hello', delegation.call
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'does not delegate when given a class' do
|
49
|
-
client = test_person
|
50
|
-
assert_raises(TypeError){
|
51
|
-
Casting::Delegation.new('class_defined', client).to(Unrelated)
|
52
|
-
}
|
53
|
-
end
|
54
|
-
end
|
data/test/casting_20_test.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
describe Casting::Delegation do
|
4
|
-
|
5
|
-
it 'finds the module defining a method and uses it to delegate' do
|
6
|
-
client = test_person
|
7
|
-
attendant = Unrelated.new
|
8
|
-
delegation = Casting::Delegation.new('unrelated', client).to(attendant)
|
9
|
-
assert_equal attendant.unrelated, delegation.call
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'does not delegate to methods defined in classes' do
|
13
|
-
client = test_person
|
14
|
-
attendant = Unrelated.new
|
15
|
-
assert_raises(TypeError){
|
16
|
-
Casting::Delegation.new('class_defined', client).to(attendant)
|
17
|
-
}
|
18
|
-
end
|
19
|
-
end
|