multiplexing_delegator 0.1.0 → 0.1.1
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.
- data/History.txt +6 -0
- data/README.txt +22 -3
- data/lib/multiplexing_delegator.rb +41 -14
- data/test/test_multiplexing_delegator.rb +36 -19
- metadata +1 -1
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.1.1 / 2008-01-26
|
2
|
+
|
3
|
+
* Switched the delegation accessor from :on to :across.
|
4
|
+
* Included Enumerable and will now treat methods to call on the delegated methods differently than methods Enumerable like #map, #inject, etc.
|
5
|
+
* Stopped deciding whether or not return to nils and are just returning whatever is available. User can compact if they do not want nils.
|
6
|
+
|
1
7
|
== 0.1.0 / 2008-01-25
|
2
8
|
|
3
9
|
* Birth to the MultiplexingDelegator!
|
data/README.txt
CHANGED
@@ -21,16 +21,19 @@ accessors for a given object instance and aggregating the results.
|
|
21
21
|
Example
|
22
22
|
class Foo
|
23
23
|
attr_accessor :baz, :bum
|
24
|
-
multiplex :bar, :
|
24
|
+
multiplex :bar, :across => [:baz, :bum]
|
25
25
|
end
|
26
26
|
|
27
27
|
foo = Foo.new
|
28
28
|
foo.baz = 1
|
29
|
-
foo.bum =
|
29
|
+
foo.bum = 'boo'
|
30
30
|
foo.bar.map => [1, 'boo']
|
31
|
+
foo.bar.each {|item| puts "Yo yo #{item}"}
|
32
|
+
=> Yo yo 1
|
33
|
+
=> Yo yo boo
|
31
34
|
|
32
35
|
You can also proxy method calls to each of the delegated items and results
|
33
|
-
will be aggregated.
|
36
|
+
will be aggregated. This was the actual impetus behind writing this little gem.
|
34
37
|
|
35
38
|
Example
|
36
39
|
class Goo
|
@@ -43,6 +46,22 @@ Example
|
|
43
46
|
foo.bum = Goo.new('world')
|
44
47
|
foo.bar.car => ['hello, 'world']
|
45
48
|
|
49
|
+
A feature of multiplex that you may not expect is that it will flatten
|
50
|
+
arrays to one-level deep so as to simulate a single stream of results. For
|
51
|
+
instance, using Foo from above:
|
52
|
+
|
53
|
+
foo = Foo.new
|
54
|
+
foo.baz = 'hello world'
|
55
|
+
foo.bum = ['how', 'are', 'you]
|
56
|
+
foo.bar.map => ['hello world', 'how', 'are', 'you']
|
57
|
+
|
58
|
+
However, multiplex will not flatten more than one level deep. For example:
|
59
|
+
|
60
|
+
foo = Foo.new
|
61
|
+
foo.baz = [['hello', 'world']]
|
62
|
+
foo.bum = [['how', 'are', 'you]]
|
63
|
+
foo.bar.map => [['hello', 'world'], ['how', 'are', 'you']]
|
64
|
+
|
46
65
|
== REQUIREMENTS:
|
47
66
|
|
48
67
|
Ruby 1.8.6 and above
|
@@ -1,9 +1,6 @@
|
|
1
|
-
# class MultiplexingDelegator
|
2
|
-
# VERSION = '0.1.0'
|
3
|
-
# end
|
4
1
|
module Glomp #:nodoc:
|
5
2
|
module MultiplexingDelegator #:nodoc:
|
6
|
-
VERSION = '0.1.
|
3
|
+
VERSION = '0.1.1'
|
7
4
|
|
8
5
|
# The multiplex class method is used to define a delegator method that
|
9
6
|
# multiplexes calls to a method across many methods for an instance of an
|
@@ -16,12 +13,12 @@ module Glomp #:nodoc:
|
|
16
13
|
# Example
|
17
14
|
# class Foo
|
18
15
|
# attr_accessor :baz, :bum
|
19
|
-
# multiplex :bar, :
|
16
|
+
# multiplex :bar, :across => [:baz, :bum]
|
20
17
|
# end
|
21
18
|
#
|
22
19
|
# foo = Foo.new
|
23
20
|
# foo.baz = 1
|
24
|
-
# foo.bum =
|
21
|
+
# foo.bum = 'boo'
|
25
22
|
# foo.bar.map => [1, 'boo']
|
26
23
|
# foo.bar.each {|item| puts "Yo yo #{item}"}
|
27
24
|
# => Yo yo 1
|
@@ -41,9 +38,25 @@ module Glomp #:nodoc:
|
|
41
38
|
# foo.bum = Goo.new('world')
|
42
39
|
# foo.bar.car => ['hello, 'world']
|
43
40
|
#
|
41
|
+
# A feature of multiplex that you may not expect is that it will flatten
|
42
|
+
# arrays to one-level deep so as to simulate a single stream of results. For
|
43
|
+
# instance, using Foo from above:
|
44
|
+
#
|
45
|
+
# foo = Foo.new
|
46
|
+
# foo.baz = 'hello world'
|
47
|
+
# foo.bum = ['how', 'are', 'you]
|
48
|
+
# foo.bar.map => ['hello world', 'how', 'are', 'you']
|
49
|
+
#
|
50
|
+
# However, multiplex will not flatten more than one level deep. For example:
|
51
|
+
#
|
52
|
+
# foo = Foo.new
|
53
|
+
# foo.baz = [['hello', 'world']]
|
54
|
+
# foo.bum = [['how', 'are', 'you]]
|
55
|
+
# foo.bar.map => [['hello', 'world'], ['how', 'are', 'you']]
|
56
|
+
#
|
44
57
|
def multiplex(method, opts={})
|
45
58
|
define_method(method) do
|
46
|
-
@multiplexer ||= Multiplexer.new(method, self, opts[:
|
59
|
+
@multiplexer ||= Multiplexer.new(method, self, opts[:across])
|
47
60
|
end
|
48
61
|
end
|
49
62
|
|
@@ -52,6 +65,8 @@ module Glomp #:nodoc:
|
|
52
65
|
end
|
53
66
|
|
54
67
|
class Multiplexer < BlankSlate
|
68
|
+
include Enumerable
|
69
|
+
|
55
70
|
def initialize(name, target, on=[])
|
56
71
|
@target = target
|
57
72
|
@multiplexed = (array?(on) ? on : [on]).compact
|
@@ -61,18 +76,30 @@ module Glomp #:nodoc:
|
|
61
76
|
end
|
62
77
|
end
|
63
78
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
79
|
+
def each(&block)
|
80
|
+
multiplexed_each do |proxy_target|
|
81
|
+
if array?(proxy_target)
|
82
|
+
proxy_target.each {|proxied_value| yield(proxied_value)}
|
83
|
+
else
|
84
|
+
yield(proxy_target)
|
70
85
|
end
|
71
|
-
acc
|
72
86
|
end
|
73
87
|
end
|
88
|
+
|
89
|
+
def method_missing(sym, *args, &block)
|
90
|
+
results = []
|
91
|
+
multiplexed_each do |proxy_target|
|
92
|
+
proxy_value = proxy_target.send(sym, *args, &block) if proxy_target
|
93
|
+
results.send((array?(proxy_value) ? :+ : :<<), proxy_value)
|
94
|
+
end
|
95
|
+
results
|
96
|
+
end
|
74
97
|
|
75
98
|
private
|
99
|
+
def multiplexed_each(&block)
|
100
|
+
@multiplexed.each { |proxy_to| yield(@target.send(proxy_to))}
|
101
|
+
end
|
102
|
+
|
76
103
|
def array?(obj) obj.kind_of?(Array); end
|
77
104
|
end
|
78
105
|
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'multiplexing_delegator'
|
2
2
|
require 'test/unit'
|
3
3
|
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mocha'
|
6
|
+
|
4
7
|
class Foo
|
5
8
|
attr_accessor :bar
|
6
9
|
def initialize(bar) @bar = bar; end
|
@@ -12,14 +15,29 @@ end
|
|
12
15
|
|
13
16
|
class Family
|
14
17
|
attr_accessor :adults, :children, :pets
|
15
|
-
multiplex :members, :
|
18
|
+
multiplex :members, :across => [:adults, :children, :pets]
|
16
19
|
end
|
17
20
|
|
18
21
|
class TestMultiplexingDelegator < Test::Unit::TestCase
|
19
22
|
|
20
|
-
def
|
23
|
+
def test_should_only_create_one_multiplex_instance_per_object_instance
|
24
|
+
family = Family.new
|
25
|
+
assert_same family.members.__id__, family.members.__id__
|
26
|
+
assert_not_equal Family.new.members.__id__, family.members.__id__
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_multiplexer_should_include_single_element_number_returns
|
30
|
+
family = Family.new
|
31
|
+
family.adults = 1; family.children = 2; family.pets = 3
|
32
|
+
assert_equal [1, 2, 3], family.members.map
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_include_single_element_returns
|
21
36
|
family = Family.new
|
22
|
-
|
37
|
+
family.adults = 'mom'
|
38
|
+
family.children = ['thing 1', 'thing 2']
|
39
|
+
family.pets = 'dog'
|
40
|
+
assert_equal ['mom'] + family.children + ['dog'], family.members.map
|
23
41
|
end
|
24
42
|
|
25
43
|
def test_multiplex_returns_flat_array_when_aggregating
|
@@ -31,26 +49,17 @@ class TestMultiplexingDelegator < Test::Unit::TestCase
|
|
31
49
|
family.members.map
|
32
50
|
end
|
33
51
|
|
34
|
-
def
|
52
|
+
def test_multiplex_returns_array_of_nils_when_nothing_to_aggregate
|
35
53
|
family = Family.new
|
36
|
-
|
37
|
-
assert_not_equal Family.new.members.__id__, family.members.__id__
|
54
|
+
assert_equal [nil, nil, nil], family.members.map
|
38
55
|
end
|
39
56
|
|
40
|
-
def
|
41
|
-
family = Family.new
|
42
|
-
family.adults = 'mom'
|
43
|
-
family.children = ['thing 1', 'thing 2']
|
44
|
-
family.pets = 'dog'
|
45
|
-
assert_equal ['mom'] + family.children + ['dog'], family.members.map
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_should_ignore_nil_values
|
57
|
+
def test_should_not_ignore_nil_values_when_enumerable_kicks_in
|
49
58
|
family = Family.new
|
50
59
|
family.adults = nil
|
51
60
|
family.children = ['superfudge']
|
52
61
|
family.pets = 'dog'
|
53
|
-
assert_equal ['superfudge', 'dog'], family.members.map
|
62
|
+
assert_equal [nil, 'superfudge', 'dog'], family.members.map
|
54
63
|
end
|
55
64
|
|
56
65
|
def test_should_accept_nil_array_values
|
@@ -58,7 +67,7 @@ class TestMultiplexingDelegator < Test::Unit::TestCase
|
|
58
67
|
family.adults = [nil]
|
59
68
|
family.children = [nil]
|
60
69
|
family.pets = nil
|
61
|
-
assert_equal [nil, nil], family.members.map
|
70
|
+
assert_equal [nil, nil, nil], family.members.map
|
62
71
|
end
|
63
72
|
|
64
73
|
def test_should_throw_no_method_found_when_calling_unknown_method_on_assoc
|
@@ -82,10 +91,18 @@ class TestMultiplexingDelegator < Test::Unit::TestCase
|
|
82
91
|
assert_equal [1, 2, 3], family.members.bar
|
83
92
|
end
|
84
93
|
|
94
|
+
def test_should_not_ignore_nil_proxies
|
95
|
+
family = Family.new
|
96
|
+
family.adults = Foo.new(1)
|
97
|
+
family.children = nil
|
98
|
+
family.pets = Foo.new(3)
|
99
|
+
assert_equal [1, nil, 3], family.members.bar
|
100
|
+
end
|
101
|
+
|
85
102
|
def test_should_accept_non_array_values_for_on
|
86
103
|
family = Family.new
|
87
104
|
class << family
|
88
|
-
multiplex :foo, :
|
105
|
+
multiplex :foo, :across => :children
|
89
106
|
end
|
90
107
|
family.children = Foo.new('howdy')
|
91
108
|
assert_equal ['howdy'], family.foo.bar
|
@@ -94,7 +111,7 @@ class TestMultiplexingDelegator < Test::Unit::TestCase
|
|
94
111
|
def test_should_bail_with_a_nil_on
|
95
112
|
family = Family.new
|
96
113
|
class << family
|
97
|
-
multiplex :foo, :
|
114
|
+
multiplex :foo, :across => nil
|
98
115
|
end
|
99
116
|
assert_raise(::ArgumentError) do
|
100
117
|
family.foo.map
|