casting 0.7.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://travis-ci.org/saturnflyer/casting.png?branch=master)](https://travis-ci.org/saturnflyer/casting)
|
4
3
|
[![Code Climate](https://codeclimate.com/github/saturnflyer/casting.png)](https://codeclimate.com/github/saturnflyer/casting)
|
5
4
|
[![Test Coverage](https://codeclimate.com/github/saturnflyer/casting/badges/coverage.svg)](https://codeclimate.com/github/saturnflyer/casting/coverage)
|
6
5
|
[![Gem Version](https://badge.fury.io/rb/casting.png)](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
|