multiplexing_delegator 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|