multiplexing_delegator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.0 / 2008-01-25
2
+
3
+ * Birth to the MultiplexingDelegator!
data/Manifest.txt ADDED
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/multiplexing_delegator
6
+ lib/multiplexing_delegator.rb
7
+ test/test_multiplexing_delegator.rb
data/README.txt ADDED
@@ -0,0 +1,77 @@
1
+ MultiplexingDelegator
2
+ by Justin Knowlden
3
+ http://glomp.rubyforge.org/multiplexing_delegator
4
+
5
+ == DESCRIPTION:
6
+
7
+ MultiplexingDelegator is used to define a delegator method that
8
+ multiplexes calls from one method across many methods for an instance of an
9
+ object. The class method is usable for any type of Object, but was intended for
10
+ use within an ActiveRecord object.
11
+
12
+ The delegator works by calling the same method across multiple methods or
13
+ accessors for a given object instance and aggregating the results.
14
+
15
+ == FEATURES/PROBLEMS:
16
+
17
+ * Adds a multiplex class method to all Objects
18
+
19
+ == SYNOPSIS:
20
+
21
+ Example
22
+ class Foo
23
+ attr_accessor :baz, :bum
24
+ multiplex :bar, :on => [:baz, :bum]
25
+ end
26
+
27
+ foo = Foo.new
28
+ foo.baz = 1
29
+ foo.bum = ['boo']
30
+ foo.bar.map => [1, 'boo']
31
+
32
+ You can also proxy method calls to each of the delegated items and results
33
+ will be aggregated.
34
+
35
+ Example
36
+ class Goo
37
+ attr_accessor :car
38
+ def initialize(car) @car = car; end
39
+ end
40
+
41
+ foo = Foo.new
42
+ foo.baz = Goo.new('hello')
43
+ foo.bum = Goo.new('world')
44
+ foo.bar.car => ['hello, 'world']
45
+
46
+ == REQUIREMENTS:
47
+
48
+ Ruby 1.8.6 and above
49
+
50
+ == INSTALL:
51
+
52
+ sudo gem install multiplexing_delegator
53
+
54
+ == LICENSE:
55
+
56
+ (The MIT License)
57
+
58
+ Copyright (c) 2008 Justin Knowlden
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining
61
+ a copy of this software and associated documentation files (the
62
+ 'Software'), to deal in the Software without restriction, including
63
+ without limitation the rights to use, copy, modify, merge, publish,
64
+ distribute, sublicense, and/or sell copies of the Software, and to
65
+ permit persons to whom the Software is furnished to do so, subject to
66
+ the following conditions:
67
+
68
+ The above copyright notice and this permission notice shall be
69
+ included in all copies or substantial portions of the Software.
70
+
71
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
72
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
73
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
74
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
75
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
76
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
77
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/multiplexing_delegator.rb'
6
+
7
+ Hoe.new('MultiplexingDelegator', Glomp::MultiplexingDelegator::VERSION) do |p|
8
+ p.name = 'multiplexing_delegator'
9
+ p.rubyforge_name = 'glomp'
10
+ p.author = 'Justin Knowlden'
11
+ p.email = 'justin@goglomp.net'
12
+ p.summary = 'Define a single delegator method that multiplexes calls across multiple methods within an Object'
13
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
14
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
15
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
16
+ p.remote_rdoc_dir = 'multiplexing_delegator'
17
+ end
18
+
19
+ # vim: syntax=Ruby
File without changes
@@ -0,0 +1,82 @@
1
+ # class MultiplexingDelegator
2
+ # VERSION = '0.1.0'
3
+ # end
4
+ module Glomp #:nodoc:
5
+ module MultiplexingDelegator #:nodoc:
6
+ VERSION = '0.1.0'
7
+
8
+ # The multiplex class method is used to define a delegator method that
9
+ # multiplexes calls to a method across many methods for an instance of an
10
+ # object. The class method is usable for any type of Object, not just
11
+ # ActiveRecord objects.
12
+ #
13
+ # The delegator works by calling the same method across multiple methods or
14
+ # accessors for a given object instance and aggregating the results.
15
+ #
16
+ # Example
17
+ # class Foo
18
+ # attr_accessor :baz, :bum
19
+ # multiplex :bar, :on => [:baz, :bum]
20
+ # end
21
+ #
22
+ # foo = Foo.new
23
+ # foo.baz = 1
24
+ # foo.bum = ['boo']
25
+ # foo.bar.map => [1, 'boo']
26
+ # foo.bar.each {|item| puts "Yo yo #{item}"}
27
+ # => Yo yo 1
28
+ # => Yo yo boo
29
+ #
30
+ # You can also proxy method calls to each of the delegated items and results
31
+ # will be aggregated.
32
+ #
33
+ # Example
34
+ # class Goo
35
+ # attr_accessor :car
36
+ # def initialize(car) @car = car; end
37
+ # end
38
+ #
39
+ # foo = Foo.new
40
+ # foo.baz = Goo.new('hello')
41
+ # foo.bum = Goo.new('world')
42
+ # foo.bar.car => ['hello, 'world']
43
+ #
44
+ def multiplex(method, opts={})
45
+ define_method(method) do
46
+ @multiplexer ||= Multiplexer.new(method, self, opts[:on])
47
+ end
48
+ end
49
+
50
+ class BlankSlate
51
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
52
+ end
53
+
54
+ class Multiplexer < BlankSlate
55
+ def initialize(name, target, on=[])
56
+ @target = target
57
+ @multiplexed = (array?(on) ? on : [on]).compact
58
+ if @multiplexed == []
59
+ raise ::ArgumentError.new(
60
+ "Must specify delegation methods for #{name.inspect} multiplexer")
61
+ end
62
+ end
63
+
64
+ def method_missing(sym, *args, &block)
65
+ @multiplexed.inject([]) do |acc, proxy_to|
66
+ proxy_target = @target.send(proxy_to)
67
+ if proxy_target
68
+ val = proxy_target.send(sym, *args, &block)
69
+ acc = acc.send((array?(val) ? :+ : :<<), val)
70
+ end
71
+ acc
72
+ end
73
+ end
74
+
75
+ private
76
+ def array?(obj) obj.kind_of?(Array); end
77
+ end
78
+
79
+ end # MultiplexingDelegator
80
+ end # Glomp
81
+
82
+ Object.send(:extend, Glomp::MultiplexingDelegator)
@@ -0,0 +1,113 @@
1
+ require 'multiplexing_delegator'
2
+ require 'test/unit'
3
+
4
+ class Foo
5
+ attr_accessor :bar
6
+ def initialize(bar) @bar = bar; end
7
+
8
+ def baz(&block)
9
+ "#{@bar} #{yield}"
10
+ end
11
+ end
12
+
13
+ class Family
14
+ attr_accessor :adults, :children, :pets
15
+ multiplex :members, :on => [:adults, :children, :pets]
16
+ end
17
+
18
+ class TestMultiplexingDelegator < Test::Unit::TestCase
19
+
20
+ def test_multiplex_returns_empty_array_when_nothing_to_aggregate
21
+ family = Family.new
22
+ assert_equal [], family.members.map
23
+ end
24
+
25
+ def test_multiplex_returns_flat_array_when_aggregating
26
+ family = Family.new
27
+ family.adults = ['mom', 'dad']
28
+ family.children = ['thing 1', 'thing 2']
29
+ family.pets = ['dog', 'cat']
30
+ assert_equal family.adults + family.children + family.pets,
31
+ family.members.map
32
+ end
33
+
34
+ def test_should_only_create_one_multiplex_instance_per_object_instance
35
+ family = Family.new
36
+ assert_same family.members.__id__, family.members.__id__
37
+ assert_not_equal Family.new.members.__id__, family.members.__id__
38
+ end
39
+
40
+ def test_should_include_single_element_returns
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
49
+ family = Family.new
50
+ family.adults = nil
51
+ family.children = ['superfudge']
52
+ family.pets = 'dog'
53
+ assert_equal ['superfudge', 'dog'], family.members.map
54
+ end
55
+
56
+ def test_should_accept_nil_array_values
57
+ family = Family.new
58
+ family.adults = [nil]
59
+ family.children = [nil]
60
+ family.pets = nil
61
+ assert_equal [nil, nil], family.members.map
62
+ end
63
+
64
+ def test_should_throw_no_method_found_when_calling_unknown_method_on_assoc
65
+ family = Family.new
66
+ assert_raise(NoMethodError) { family.methods.foo }
67
+ end
68
+
69
+ def test_should_only_flatten_array_for_first_level_elements
70
+ family = Family.new
71
+ family.adults = [[1], [2]]
72
+ family.children = [['a'], 'b']
73
+ family.pets = 'dog'
74
+ assert_equal [[1], [2], ['a'], 'b', 'dog'], family.members.map
75
+ end
76
+
77
+ def test_should_proxy_any_method
78
+ family = Family.new
79
+ family.adults = Foo.new(1)
80
+ family.children = Foo.new(2)
81
+ family.pets = Foo.new(3)
82
+ assert_equal [1, 2, 3], family.members.bar
83
+ end
84
+
85
+ def test_should_accept_non_array_values_for_on
86
+ family = Family.new
87
+ class << family
88
+ multiplex :foo, :on => :children
89
+ end
90
+ family.children = Foo.new('howdy')
91
+ assert_equal ['howdy'], family.foo.bar
92
+ end
93
+
94
+ def test_should_bail_with_a_nil_on
95
+ family = Family.new
96
+ class << family
97
+ multiplex :foo, :on => nil
98
+ end
99
+ assert_raise(::ArgumentError) do
100
+ family.foo.map
101
+ end
102
+ end
103
+
104
+ def test_should_proxy_blocks
105
+ family = Family.new
106
+ family.adults = Foo.new(1)
107
+ family.children = Foo.new(2)
108
+ family.pets = Foo.new(3)
109
+ aggregate_baz = family.members.baz {'foo'}
110
+ assert_equal ['1 foo', '2 foo', '3 foo'], aggregate_baz
111
+ end
112
+
113
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multiplexing_delegator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Justin Knowlden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-26 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.4.0
23
+ version:
24
+ description: "The delegator works by calling the same method across multiple methods or accessors for a given object instance and aggregating the results. == FEATURES/PROBLEMS: * Adds a multiplex class method to all Objects == SYNOPSIS:"
25
+ email: justin@goglomp.net
26
+ executables:
27
+ - multiplexing_delegator
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - Manifest.txt
33
+ - README.txt
34
+ files:
35
+ - History.txt
36
+ - Manifest.txt
37
+ - README.txt
38
+ - Rakefile
39
+ - bin/multiplexing_delegator
40
+ - lib/multiplexing_delegator.rb
41
+ - test/test_multiplexing_delegator.rb
42
+ has_rdoc: true
43
+ homepage: " by Justin Knowlden"
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --main
47
+ - README.txt
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project: glomp
65
+ rubygems_version: 1.0.1
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: Define a single delegator method that multiplexes calls across multiple methods within an Object
69
+ test_files:
70
+ - test/test_multiplexing_delegator.rb