needle-extras 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.
@@ -0,0 +1,17 @@
1
+ require 'needle/extras/require-library'
2
+
3
+ module Needle
4
+ module Extras
5
+
6
+ def register_services( container )
7
+ container.define do |b|
8
+ b.require 'needle/extras/attr-inject', 'Needle::Extras::AttrInject'
9
+ b.require 'needle/extras/multicast', 'Needle::Extras::Multicast'
10
+ end
11
+ end
12
+ module_function :register_services
13
+
14
+ end
15
+
16
+ register_library "needle/extras", Needle::Extras
17
+ end
@@ -0,0 +1,73 @@
1
+ require 'needle/pipeline/element'
2
+
3
+ class Class
4
+
5
+ # Add a hook for declaring properties of an object that should be injected
6
+ # into instances of this class. See Object#inject_attributes.
7
+ def attr_inject( *properties )
8
+ ( @injectable_attributes ||= [] ).concat properties.map { |p| p.to_sym }
9
+ end
10
+ private :attr_inject
11
+
12
+ # Returns an array of attributes of the class that have been declared to
13
+ # be injectable. See #attr_inject and Object#inject_attributes.
14
+ def injectable_attributes
15
+ if defined?(@injectable_attributes)
16
+ @injectable_attributes
17
+ else
18
+ []
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ class Object
25
+
26
+ # Injects all injectable attributes of the instance's class with the
27
+ # corresponding services from the given container. Each attribute is
28
+ # injected into an identically named instance variable of the object,
29
+ # from an identically named service in the container.
30
+ #
31
+ # This returns the object itself.
32
+ def inject_attributes( container )
33
+ self.class.injectable_attributes.each do |attribute|
34
+ instance_variable_set "@#{attribute}", container.get( attribute )
35
+ end
36
+ self
37
+ end
38
+
39
+ end
40
+
41
+ module Needle
42
+ module Extras
43
+ module AttrInject
44
+
45
+ # A specialized pipeline element that injects the constructed service
46
+ # with dependent services from the point's container.
47
+ class InjectorElement < Needle::Pipeline::Element
48
+ set_default_priority 0
49
+
50
+ def call( *args )
51
+ succ.
52
+ call( *args ).
53
+ inject_attributes( service_point.container )
54
+ end
55
+
56
+ end
57
+
58
+ # Registers the InjectorElement pipeline element, and adds some new
59
+ # service models (multiton_inject, prototype_inject, and
60
+ # singleton_inject).
61
+ def register_services( container )
62
+ container.pipeline_elements[ :attr_inject ] = InjectorElement
63
+ container.service_models.update(
64
+ :multiton_inject => [ :multiton, :attr_inject ],
65
+ :prototype_inject => [ :attr_injector ],
66
+ :singleton_inject => [ :singleton, :attr_inject ]
67
+ )
68
+ end
69
+ module_function :register_services
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,42 @@
1
+ module Needle
2
+ module Extras
3
+ module Multicast
4
+
5
+ # A proxy that wraps an array of other objects. Whenever a message
6
+ # is received by this proxy, it delegates the call to the objects in the
7
+ # array.
8
+ class Target
9
+
10
+ # Creates a new Target object that acts as a proxy for the given list
11
+ # of delegates.
12
+ def initialize( *delegates )
13
+ @delegates = delegates
14
+ end
15
+
16
+ # Forwards the method to each object in the array. It does no checking
17
+ # to ensure that the receiver can understand the message before sending
18
+ # it. This will return an array of the results of calling each of the
19
+ # other messages.
20
+ def method_missing( sym, *args, &block )
21
+ @delegates.inject( [] ) do |a,d|
22
+ a << d.__send__( sym, *args, &block )
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ # Register the multicast factory service in the given container. The
29
+ # multicast service is a parameterized service which accepts a single
30
+ # parameter--an array of the targets to apply to the multicaster. It
31
+ # will then return an instance of a multicast service.
32
+ def register_services( container )
33
+ container.define.multicast :model => :prototype do |c,p,*targets|
34
+ Multicast::Target.new( *targets )
35
+ end
36
+ end
37
+ module_function :register_services
38
+
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,34 @@
1
+ require 'needle/container'
2
+
3
+ module Needle
4
+
5
+ # This constant represents the collection of registered libraries. Each
6
+ # value in it must respond to the #call method, accepting a single
7
+ # parameter (the container to register the library with).
8
+ LIBRARIES = Hash.new
9
+
10
+ class Container
11
+
12
+ # Require the library registered under the given name. A Kernel.require
13
+ # is done on the name, and then if a library has been registered under
14
+ # that name, its #call method is invoked with the container as the
15
+ # parameter.
16
+ def require_library( name )
17
+ Kernel.require name
18
+ LIBRARIES[ name ].call( self ) if LIBRARIES[ name ]
19
+ end
20
+
21
+ end
22
+
23
+ # A convenience method for registering libraries with the "require-library"
24
+ # subsystem. +name+ must correspond to a file to require with Kernel.require.
25
+ # +mod+ is a module containing the registration method named by the
26
+ # +registration_method+ parameter (defaulting to <tt>:register_library</tt>).
27
+ def register_library( name, mod, registration_method=:register_services )
28
+ LIBRARIES[ name ] = lambda do |container|
29
+ mod.__send__( registration_method, container )
30
+ end
31
+ end
32
+ module_function :register_library
33
+
34
+ end
@@ -0,0 +1,13 @@
1
+ module Needle
2
+ module Extras
3
+ module Version
4
+
5
+ MAJOR = 1
6
+ MINOR = 0
7
+ TINY = 0
8
+
9
+ STRING = [MAJOR,MINOR,TINY].join('.')
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ $:.unshift "../lib"
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue LoadError
6
+ end
7
+
8
+ Dir.chdir File.dirname(__FILE__)
9
+ Dir["**/tc_*.rb"].each { |file| load file }
@@ -0,0 +1,115 @@
1
+ $:.unshift "../lib"
2
+
3
+ require 'test/unit'
4
+ require 'needle'
5
+ require 'needle/extras/attr-inject'
6
+
7
+ class TC_AttrInject_Class < Test::Unit::TestCase
8
+
9
+ def test_attr_inject
10
+ assert_nothing_raised do
11
+ Class.new do
12
+ attr_inject :foo
13
+ attr_inject :bar, :baz
14
+ attr_inject "test"
15
+ end
16
+ end
17
+ end
18
+
19
+ def test_injectable_attributes
20
+ klass = Class.new do
21
+ attr_inject :foo
22
+ attr_inject :bar, :baz
23
+ attr_inject "test"
24
+ end
25
+ assert_equal [ :foo, :bar, :baz, :test ], klass.injectable_attributes
26
+ end
27
+
28
+ end
29
+
30
+
31
+ class AttrInject_MockContainer
32
+ def get( attribute )
33
+ attribute
34
+ end
35
+ end
36
+
37
+
38
+ class TC_AttrInject_Object < Test::Unit::TestCase
39
+
40
+ def test_inject_attributes
41
+ klass = Class.new { attr_inject :foo, :bar }
42
+ obj = klass.new.inject_attributes( AttrInject_MockContainer.new )
43
+ assert_equal :foo, obj.instance_variable_get( "@foo" )
44
+ assert_equal :bar, obj.instance_variable_get( "@bar" )
45
+ end
46
+
47
+ end
48
+
49
+
50
+ class TC_AttrInject_InjectorElement < Test::Unit::TestCase
51
+
52
+ def setup
53
+ point = Class.new do
54
+ attr_reader :container
55
+ def initialize( c ); @container = c; end
56
+ end.new( AttrInject_MockContainer.new )
57
+
58
+ klass = Class.new { attr_inject :foo, :bar }
59
+
60
+ @element = Needle::Extras::AttrInject::InjectorElement.new( point )
61
+ @element.succ = proc { klass.new }
62
+ end
63
+
64
+ def test_default_priority
65
+ assert_equal 0, @element.priority
66
+ end
67
+
68
+ def test_call_multiargs
69
+ assert_nothing_raised do
70
+ @element.call( 1, 2, 3 )
71
+ end
72
+ end
73
+
74
+ def test_call
75
+ obj = @element.call( 1, 2, 3 )
76
+ assert_equal :foo, obj.instance_variable_get( "@foo" )
77
+ assert_equal :bar, obj.instance_variable_get( "@bar" )
78
+ end
79
+
80
+ end
81
+
82
+
83
+ class TC_AttrInject_Services < Test::Unit::TestCase
84
+
85
+ def setup
86
+ @reg = Needle::Registry.new
87
+ Needle::Extras::AttrInject.register_services( @reg )
88
+ @reg.register( :foo ) { "foo is wizard!" }
89
+ @reg.register( :bar ) { "bar is teh bomb!" }
90
+ end
91
+
92
+ def test_no_inject
93
+ @reg.register( :hit_me, :model => :singleton_inject ) do
94
+ Class.new { def hello; "hello"; end }.new
95
+ end
96
+ hit_me = nil
97
+ assert_nothing_raised do
98
+ hit_me = @reg.hit_me
99
+ end
100
+ assert_equal "hello", hit_me.hello
101
+ end
102
+
103
+ def test_inject
104
+ @reg.register( :hit_me, :model => :singleton_inject ) do
105
+ Class.new { attr_inject :foo, :bar; attr_reader :foo, :bar }.new
106
+ end
107
+ hit_me = nil
108
+ assert_nothing_raised do
109
+ hit_me = @reg.hit_me
110
+ end
111
+ assert_equal "foo is wizard!", hit_me.foo
112
+ assert_equal "bar is teh bomb!", hit_me.bar
113
+ end
114
+
115
+ end
@@ -0,0 +1,46 @@
1
+ $:.unshift "../lib"
2
+
3
+ require 'test/unit'
4
+ require 'needle'
5
+ require 'needle/extras/multicast'
6
+
7
+ class TC_Multicast_Target < Test::Unit::TestCase
8
+
9
+ def test_empty_delegation
10
+ target = Needle::Extras::Multicast::Target.new
11
+ assert_equal [], target.length
12
+ end
13
+
14
+ def test_non_empty_delegation
15
+ target = Needle::Extras::Multicast::Target.new( "foo", "bar baz",
16
+ [ 1, 2, 3, 4, 5 ] )
17
+ assert_equal [ 3, 7, 5 ], target.length
18
+ end
19
+
20
+ def test_send_bad_message
21
+ target = Needle::Extras::Multicast::Target.new( 5 )
22
+ assert_raise( NoMethodError ) do
23
+ target.length
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ class TC_Multicast_Service < Test::Unit::TestCase
30
+
31
+ def test_service
32
+ reg = Needle::Registry.define do |b|
33
+ b.require 'needle/extras/multicast', Needle::Extras::Multicast
34
+
35
+ b.a { "a" }
36
+ b.b { "b" }
37
+ b.c { |c,| [ c.a, c.b, "c" ] }
38
+
39
+ b.sender { |c,| c.multicast( c.a, c.c ) }
40
+ end
41
+
42
+ sender = reg.sender
43
+ assert_equal [ 1, 3 ], sender.length
44
+ end
45
+
46
+ end
@@ -0,0 +1,70 @@
1
+ $:.unshift "../lib"
2
+
3
+ require 'test/unit'
4
+ require 'needle'
5
+ require 'needle/extras/require-library'
6
+
7
+ class TC_RequireLibrary_Container < Test::Unit::TestCase
8
+
9
+ def test_require_library_registered
10
+ reg = Needle::Registry.new
11
+ assert !reg.keys.include?( :multicast )
12
+ reg.require_library "needle/extras"
13
+ assert reg.keys.include?( :multicast )
14
+ end
15
+
16
+ def test_require_library_unregistered
17
+ reg = Needle::Registry.new
18
+ assert_nothing_raised do
19
+ reg.require_library "rational"
20
+ end
21
+ end
22
+
23
+ def test_require_library_custom_hook
24
+ called_by = nil
25
+ Needle::LIBRARIES['yaml'] = lambda { |container| called_by = container }
26
+ reg = Needle::Registry.new
27
+ reg.require_library "yaml"
28
+ assert_same called_by, reg
29
+ end
30
+
31
+ end
32
+
33
+ class TC_RequireLibrary_Needle < Test::Unit::TestCase
34
+
35
+ Klass = Class.new do
36
+ attr_reader :events
37
+
38
+ def method_missing( sym, *args )
39
+ @events ||= []
40
+ @events << [ sym, *args ]
41
+ end
42
+ end
43
+
44
+ def test_register_library
45
+ mod = Klass.new
46
+
47
+ assert !Needle::LIBRARIES.has_key?( "openssl" )
48
+ Needle.register_library( "openssl", mod )
49
+ assert Needle::LIBRARIES.has_key?( "openssl" )
50
+
51
+ reg = Needle::Registry.new
52
+ reg.require_library "openssl"
53
+
54
+ assert_equal [ [ :register_services, reg ] ], mod.events
55
+ end
56
+
57
+ def test_register_library_custom_method
58
+ mod = Klass.new
59
+
60
+ assert !Needle::LIBRARIES.has_key?( "net/http" )
61
+ Needle.register_library( "net/http", mod, :register_foo )
62
+ assert Needle::LIBRARIES.has_key?( "net/http" )
63
+
64
+ reg = Needle::Registry.new
65
+ reg.require_library "net/http"
66
+
67
+ assert_equal [ [ :register_foo, reg ] ], mod.events
68
+ end
69
+
70
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.1
3
+ specification_version: 1
4
+ name: needle-extras
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2004-11-18
8
+ summary: Needle-Extras is a collection of additional services that can be used with Needle. This is basically a test-bed of services that may eventually find their way into Needle itself.
9
+ require_paths:
10
+ - lib
11
+ author: Jamis Buck
12
+ email: jgb3@email.byu.edu
13
+ homepage: http://needle.rubyforge.org
14
+ rubyforge_project:
15
+ description:
16
+ autorequire: needle/extras
17
+ default_executable:
18
+ bindir: bin
19
+ has_rdoc: true
20
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
21
+ requirements:
22
+ -
23
+ - ">"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.0.0
26
+ version:
27
+ platform: ruby
28
+ files:
29
+ - doc/README
30
+ - doc/LICENSE-RUBY
31
+ - doc/manual-html
32
+ - doc/LICENSE-BSD
33
+ - doc/LICENSE-GPL
34
+ - doc/manual
35
+ - doc/manual-html/manual.css
36
+ - doc/manual-html/chapter-1.html
37
+ - doc/manual-html/chapter-2.html
38
+ - doc/manual-html/chapter-3.html
39
+ - doc/manual-html/chapter-4.html
40
+ - doc/manual-html/index.html
41
+ - doc/manual/manual.css
42
+ - doc/manual/manual.yml
43
+ - doc/manual/parts
44
+ - doc/manual/chapter.erb
45
+ - doc/manual/page.erb
46
+ - doc/manual/index.erb
47
+ - doc/manual/manual.rb
48
+ - doc/manual/parts/multicast_usage.txt
49
+ - doc/manual/parts/multicast_overview.txt
50
+ - doc/manual/parts/intro_usage.txt
51
+ - doc/manual/parts/attrinject_usage.txt
52
+ - doc/manual/parts/requirelibrary_overview.txt
53
+ - doc/manual/parts/intro_license.txt
54
+ - doc/manual/parts/attrinject_overview.txt
55
+ - doc/manual/parts/intro_support.txt
56
+ - doc/manual/parts/requirelibrary_usage.txt
57
+ - doc/manual/parts/intro_what_is_extras.txt
58
+ - lib/needle
59
+ - lib/needle/extras
60
+ - lib/needle/extras.rb
61
+ - lib/needle/extras/attr-inject.rb
62
+ - lib/needle/extras/multicast.rb
63
+ - lib/needle/extras/version.rb
64
+ - lib/needle/extras/require-library.rb
65
+ - test/ALL-TESTS.rb
66
+ - test/tc_attr-inject.rb
67
+ - test/tc_multicast.rb
68
+ - test/tc_require-library.rb
69
+ test_files:
70
+ - test/ALL-TESTS.rb
71
+ rdoc_options:
72
+ - "--title"
73
+ - "Needle-Extras -- Services for Needle"
74
+ - "--main"
75
+ - doc/README
76
+ extra_rdoc_files:
77
+ - doc/README
78
+ executables: []
79
+ extensions: []
80
+ requirements: []
81
+ dependencies:
82
+ - !ruby/object:Gem::Dependency
83
+ name: needle
84
+ version_requirement:
85
+ version_requirements: !ruby/object:Gem::Version::Requirement
86
+ requirements:
87
+ -
88
+ - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 1.2.0
91
+ version: