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.
- data/doc/LICENSE-BSD +27 -0
- data/doc/LICENSE-GPL +280 -0
- data/doc/LICENSE-RUBY +56 -0
- data/doc/README +50 -0
- data/doc/manual-html/chapter-1.html +214 -0
- data/doc/manual-html/chapter-2.html +180 -0
- data/doc/manual-html/chapter-3.html +168 -0
- data/doc/manual-html/chapter-4.html +184 -0
- data/doc/manual-html/index.html +155 -0
- data/doc/manual-html/manual.css +192 -0
- data/doc/manual/chapter.erb +18 -0
- data/doc/manual/index.erb +29 -0
- data/doc/manual/manual.css +192 -0
- data/doc/manual/manual.rb +202 -0
- data/doc/manual/manual.yml +45 -0
- data/doc/manual/page.erb +71 -0
- data/doc/manual/parts/attrinject_overview.txt +1 -0
- data/doc/manual/parts/attrinject_usage.txt +34 -0
- data/doc/manual/parts/intro_license.txt +5 -0
- data/doc/manual/parts/intro_support.txt +1 -0
- data/doc/manual/parts/intro_usage.txt +30 -0
- data/doc/manual/parts/intro_what_is_extras.txt +7 -0
- data/doc/manual/parts/multicast_overview.txt +1 -0
- data/doc/manual/parts/multicast_usage.txt +22 -0
- data/doc/manual/parts/requirelibrary_overview.txt +5 -0
- data/doc/manual/parts/requirelibrary_usage.txt +34 -0
- data/lib/needle/extras.rb +17 -0
- data/lib/needle/extras/attr-inject.rb +73 -0
- data/lib/needle/extras/multicast.rb +42 -0
- data/lib/needle/extras/require-library.rb +34 -0
- data/lib/needle/extras/version.rb +13 -0
- data/test/ALL-TESTS.rb +9 -0
- data/test/tc_attr-inject.rb +115 -0
- data/test/tc_multicast.rb +46 -0
- data/test/tc_require-library.rb +70 -0
- metadata +91 -0
@@ -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
|
data/test/ALL-TESTS.rb
ADDED
@@ -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:
|