pluggability 0.0.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.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/ChangeLog +690 -0
- data/History.rdoc +4 -0
- data/Manifest.txt +8 -0
- data/README.rdoc +237 -0
- data/Rakefile +31 -0
- data/lib/pluggability.rb +343 -0
- data/spec/lib/helpers.rb +31 -0
- data/spec/pluggability_spec.rb +198 -0
- metadata +212 -0
- metadata.gz.sig +1 -0
data/spec/lib/helpers.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
BEGIN {
|
5
|
+
require 'pathname'
|
6
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent
|
7
|
+
|
8
|
+
libdir = basedir + "lib"
|
9
|
+
|
10
|
+
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
11
|
+
}
|
12
|
+
|
13
|
+
require 'rspec'
|
14
|
+
require 'loggability/spechelpers'
|
15
|
+
require 'pluggability'
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
### Mock with Rspec
|
20
|
+
RSpec.configure do |config|
|
21
|
+
ruby_version_vec = RUBY_VERSION.split('.').map {|c| c.to_i }.pack( "N*" )
|
22
|
+
|
23
|
+
config.include( Loggability::SpecHelpers )
|
24
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
25
|
+
|
26
|
+
config.mock_with :rspec
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# vim: set nosta noet ts=4 sw=4:
|
31
|
+
|
@@ -0,0 +1,198 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
BEGIN {
|
4
|
+
require 'pathname'
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent
|
6
|
+
|
7
|
+
libdir = basedir + "lib"
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
10
|
+
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
11
|
+
}
|
12
|
+
|
13
|
+
require 'rspec'
|
14
|
+
require 'logger'
|
15
|
+
require 'pluggability'
|
16
|
+
|
17
|
+
require 'spec/lib/helpers'
|
18
|
+
|
19
|
+
class Plugin
|
20
|
+
extend Pluggability
|
21
|
+
plugin_prefixes 'plugins', 'plugins/private'
|
22
|
+
end
|
23
|
+
|
24
|
+
class SubPlugin < Plugin; end
|
25
|
+
class TestingPlugin < Plugin; end
|
26
|
+
class BlackSheep < Plugin; end
|
27
|
+
module Test
|
28
|
+
class LoadablePlugin < Plugin; end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
describe Pluggability do
|
33
|
+
|
34
|
+
before( :each ) do
|
35
|
+
setup_logging( :fatal )
|
36
|
+
end
|
37
|
+
|
38
|
+
after( :each ) do
|
39
|
+
reset_logging()
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
it "allows extended objects to declare one or more prefixes to use when requiring derviatives" do
|
44
|
+
Plugin.plugin_prefixes.should == ['plugins', 'plugins/private']
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
context "-extended class" do
|
50
|
+
|
51
|
+
it "knows about all of its derivatives" do
|
52
|
+
Plugin.derivatives.keys.should include( 'sub' )
|
53
|
+
Plugin.derivatives.keys.should include( 'subplugin' )
|
54
|
+
Plugin.derivatives.keys.should include( 'SubPlugin' )
|
55
|
+
Plugin.derivatives.keys.should include( SubPlugin )
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns derivatives directly if they're already loaded" do
|
59
|
+
class AlreadyLoadedPlugin < Plugin; end
|
60
|
+
Kernel.should_not_receive( :require )
|
61
|
+
Plugin.create( 'alreadyloaded' ).should be_an_instance_of( AlreadyLoadedPlugin )
|
62
|
+
Plugin.create( 'AlreadyLoaded' ).should be_an_instance_of( AlreadyLoadedPlugin )
|
63
|
+
Plugin.create( 'AlreadyLoadedPlugin' ).should be_an_instance_of( AlreadyLoadedPlugin )
|
64
|
+
Plugin.create( AlreadyLoadedPlugin ).should be_an_instance_of( AlreadyLoadedPlugin )
|
65
|
+
end
|
66
|
+
|
67
|
+
it "filters errors that happen when creating an instance of derivatives so they " +
|
68
|
+
"point to the right place" do
|
69
|
+
class PugilistPlugin < Plugin
|
70
|
+
def initialize
|
71
|
+
raise "Oh noes -- an error!"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
exception = nil
|
76
|
+
begin
|
77
|
+
Plugin.create('pugilist')
|
78
|
+
rescue ::RuntimeError => err
|
79
|
+
exception = err
|
80
|
+
else
|
81
|
+
fail "Expected an exception to be raised."
|
82
|
+
end
|
83
|
+
|
84
|
+
exception.backtrace.first.should =~ /#{__FILE__}/
|
85
|
+
end
|
86
|
+
|
87
|
+
it "will refuse to create an object other than one of its derivatives" do
|
88
|
+
class Doppelgaenger; end
|
89
|
+
expect {
|
90
|
+
Plugin.create(Doppelgaenger)
|
91
|
+
}.to raise_error( ArgumentError, /is not a descendent of/ )
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
it "will load new plugins from the require path if they're not loaded yet" do
|
96
|
+
loaded_class = nil
|
97
|
+
|
98
|
+
Plugin.should_receive( :require ).with( 'plugins/dazzle_plugin' ).and_return do |*args|
|
99
|
+
loaded_class = Class.new( Plugin )
|
100
|
+
# Simulate a named class, since we're not really requiring
|
101
|
+
Plugin.derivatives['dazzle'] = loaded_class
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
Plugin.create( 'dazzle' ).should be_an_instance_of( loaded_class )
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
it "will output a sensible description of what it tried to load if requiring a " +
|
110
|
+
"derivative fails" do
|
111
|
+
|
112
|
+
# at least 6 -> 3 variants * 2 paths
|
113
|
+
Plugin.should_receive( :require ).
|
114
|
+
at_least(6).times.
|
115
|
+
and_return {|path| raise LoadError, "path" }
|
116
|
+
|
117
|
+
expect {
|
118
|
+
Plugin.create('scintillating')
|
119
|
+
}.to raise_error( Pluggability::FactoryError, /couldn't find a \S+ named \S+.*tried \[/i )
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
it "will output a sensible description when a require succeeds, but it loads something unintended" do
|
124
|
+
# at least 6 -> 3 variants * 2 paths
|
125
|
+
Plugin.should_receive( :require ).and_return( true )
|
126
|
+
|
127
|
+
expect {
|
128
|
+
Plugin.create('corruscating')
|
129
|
+
}.to raise_error( Pluggability::FactoryError, /Require of '\S+' succeeded, but didn't load a Plugin/i )
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
it "will re-raise the first exception raised when attempting to load a " +
|
134
|
+
"derivative if none of the paths work" do
|
135
|
+
|
136
|
+
# at least 6 -> 3 variants * 2 paths
|
137
|
+
Plugin.should_receive( :require ).at_least(6).times.and_return {|path|
|
138
|
+
raise ScriptError, "error while parsing #{path}"
|
139
|
+
}
|
140
|
+
|
141
|
+
expect {
|
142
|
+
Plugin.create('portable')
|
143
|
+
}.to raise_error( ScriptError, /error while parsing/ )
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
it "can preload all of its derivatives" do
|
148
|
+
Gem.should_receive( :find_files ).with( 'plugins/*.rb' ).
|
149
|
+
and_return([ 'plugins/first.rb' ])
|
150
|
+
Gem.should_receive( :find_files ).with( 'plugins/private/*.rb' ).
|
151
|
+
and_return([ 'plugins/private/second.rb', 'plugins/private/third.rb' ])
|
152
|
+
|
153
|
+
Plugin.should_receive( :require ).with( 'plugins/first.rb' ).
|
154
|
+
and_return( true )
|
155
|
+
Plugin.should_receive( :require ).with( 'plugins/private/second.rb' ).
|
156
|
+
and_return( true )
|
157
|
+
Plugin.should_receive( :require ).with( 'plugins/private/third.rb' ).
|
158
|
+
and_return( true )
|
159
|
+
|
160
|
+
Plugin.load_all
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
context "derivative of an extended class" do
|
166
|
+
|
167
|
+
it "knows what type of factory loads it" do
|
168
|
+
TestingPlugin.factory_type.should == 'Plugin'
|
169
|
+
end
|
170
|
+
|
171
|
+
it "raises a FactoryError if it can't figure out what type of factory loads it" do
|
172
|
+
TestingPlugin.stub!( :ancestors ).and_return( [] )
|
173
|
+
expect {
|
174
|
+
TestingPlugin.factory_type
|
175
|
+
}.to raise_error( Pluggability::FactoryError, /couldn't find factory base/i )
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
context "derivative of an extended class that isn't named <Something>Plugin" do
|
181
|
+
|
182
|
+
it "is still creatable via its full name" do
|
183
|
+
Plugin.create( 'blacksheep' ).should be_an_instance_of( BlackSheep )
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
context "derivative of an extended class in another namespace" do
|
190
|
+
|
191
|
+
it "is still creatable via its derivative name" do
|
192
|
+
Plugin.create( 'loadable' ).should be_an_instance_of( Test::LoadablePlugin )
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
metadata
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pluggability
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Martin Chase
|
9
|
+
- Michael Granger
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain:
|
13
|
+
- !binary |-
|
14
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMRENDQWhTZ0F3SUJB
|
15
|
+
Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREE4TVF3d0NnWURWUVFEREFOblpX
|
16
|
+
UXgKRnpBVkJnb0praWFKay9Jc1pBRVpGZ2RmWVdWeWFXVmZNUk13RVFZS0Na
|
17
|
+
SW1pWlB5TEdRQkdSWURiM0puTUI0WApEVEV3TURreE5qRTBORGcxTVZvWERU
|
18
|
+
RXhNRGt4TmpFME5EZzFNVm93UERFTU1Bb0dBMVVFQXd3RFoyVmtNUmN3CkZR
|
19
|
+
WUtDWkltaVpQeUxHUUJHUllIWDJGbGNtbGxYekVUTUJFR0NnbVNKb21UOGl4
|
20
|
+
a0FSa1dBMjl5WnpDQ0FTSXcKRFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURD
|
21
|
+
Q0FRb0NnZ0VCQUx5Ly9CRnhDMWYvY1BTbnd0SkJXb0ZpRnJpcgpoN1JpY0kr
|
22
|
+
am9xL29jVlhRcUk0VERXUHlGLzh0cWt2dCtyRDk5WDlxczJZZVI4Q1UvWWlJ
|
23
|
+
cExXclFPWVNUNzBKCnZEbjdVdmhiMm11RlZxcTYrdm9iZVRrSUxCRU82cGlv
|
24
|
+
bldERzhqU2JvM3FLbTFSaktKRHdnOXA0d05LaFB1dTgKS0d1ZS9CRmI2N0tm
|
25
|
+
bHF5QXBQbVBlYjNWZGQ5Y2xzcHpxZUZxcDdjVUJNRXBGUzZMV3h5NEdrK3F2
|
26
|
+
RkZKQkpMQgpCVUhFL0xaVkpNVnpmcEM1VXErUW1ZN0IrRkgvUXFObmRuM3RP
|
27
|
+
SGdzUGFkTFROaW11QjFzQ3VMMWE0ejNQZXBkClRlTEJFRm1FYW81RGszSy9R
|
28
|
+
OG84dmxiSUIvakJEVFV4NkRqYmd4dzc3OTA5eDZnSTlkb1U0TEQ1WE1jQ0F3
|
29
|
+
RUEKQWFNNU1EY3dDUVlEVlIwVEJBSXdBREFMQmdOVkhROEVCQU1DQkxBd0hR
|
30
|
+
WURWUjBPQkJZRUZKZW9Ha09yOWw0Qgorc2FNa1cvWlhUNFVlU3ZWTUEwR0NT
|
31
|
+
cUdTSWIzRFFFQkJRVUFBNElCQVFCRzJLT2J2WUkyZUh5eUJVSlNKM2pOCnZF
|
32
|
+
blUzZDYwem5BWGJyU2QycWIzcjFsWTFFUEREM2JjeTBNZ2dDZkdkZzNYdTU0
|
33
|
+
ejIxb3F5SWRrOHVHdFdCUEwKSElhOUVnZkZHU1VFZ3ZjSXZhWXFpTjRqVFV0
|
34
|
+
aWRmRUZ3K0x0anM4QVA5Z1dnU0lZUzZHcjM4VjBXR0ZGTnpJSAphT0Qyd211
|
35
|
+
OW9vL1JmZlc0aFMvOEd1dmZNemN3N0NRMzU1d0ZSNEtCL255emUrRXNaMVk1
|
36
|
+
RGVyQ0FhZ01WdURRClUwQkxtV0RGelBHR1dsUGVRQ3JZSENyK0FjSnorTlJu
|
37
|
+
YUhDS0xaZFNLai9SSHVUT3QrZ2JsUmV4OEZBaDhOZUEKY21saFhlNDZwWk5K
|
38
|
+
Z1dLYnhaYWg4NWpJang5NWhSOHZPSStOQU01aUg5a09xSzEzRHJ4YWNUS1Bo
|
39
|
+
cWo1UGp3RgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
40
|
+
date: 2012-08-03 00:00:00.000000000 Z
|
41
|
+
dependencies:
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: loggability
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.5'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ~>
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0.5'
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: hoe-mercurial
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.4.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.4.0
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: hoe-highline
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ~>
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.1.0
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.1.0
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: rdoc
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ~>
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '3.10'
|
98
|
+
type: :development
|
99
|
+
prerelease: false
|
100
|
+
version_requirements: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '3.10'
|
106
|
+
- !ruby/object:Gem::Dependency
|
107
|
+
name: hoe-deveiate
|
108
|
+
requirement: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ~>
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0.1'
|
114
|
+
type: :development
|
115
|
+
prerelease: false
|
116
|
+
version_requirements: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ~>
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0.1'
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
name: hoe
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ~>
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '3.0'
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ~>
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '3.0'
|
138
|
+
description: ! 'Pluggability is a mixin module that turns an including class into
|
139
|
+
a factory for
|
140
|
+
|
141
|
+
its derivatives, capable of searching for and loading them by name. This is
|
142
|
+
|
143
|
+
useful when you have an abstract base class which defines an interface and basic
|
144
|
+
|
145
|
+
functionality for a part of a larger system, and a collection of subclasses
|
146
|
+
|
147
|
+
which implement the interface for different underlying functionality.
|
148
|
+
|
149
|
+
|
150
|
+
An example of where this might be useful is in a program which talks to a
|
151
|
+
|
152
|
+
database. To avoid coupling it to a specific database, you use a Driver class
|
153
|
+
|
154
|
+
which encapsulates your program''s interaction with the database behind a useful
|
155
|
+
|
156
|
+
interface. Now you can create a concrete implementation of the Driver class for
|
157
|
+
|
158
|
+
each kind of database you wish to talk to. If you make the base Driver class a
|
159
|
+
|
160
|
+
Pluggability, too, you can add new drivers simply by dropping them in a
|
161
|
+
|
162
|
+
directory and using the Driver''s `create` method to instantiate them:'
|
163
|
+
email:
|
164
|
+
- stillflame@FaerieMUD.org
|
165
|
+
- ged@FaerieMUD.org
|
166
|
+
executables: []
|
167
|
+
extensions: []
|
168
|
+
extra_rdoc_files:
|
169
|
+
- History.rdoc
|
170
|
+
- Manifest.txt
|
171
|
+
- README.rdoc
|
172
|
+
files:
|
173
|
+
- ChangeLog
|
174
|
+
- History.rdoc
|
175
|
+
- Manifest.txt
|
176
|
+
- README.rdoc
|
177
|
+
- Rakefile
|
178
|
+
- lib/pluggability.rb
|
179
|
+
- spec/lib/helpers.rb
|
180
|
+
- spec/pluggability_spec.rb
|
181
|
+
- .gemtest
|
182
|
+
homepage: http://deveiate.org/projects/Pluggability
|
183
|
+
licenses:
|
184
|
+
- BSD
|
185
|
+
post_install_message:
|
186
|
+
rdoc_options:
|
187
|
+
- -f
|
188
|
+
- fivefish
|
189
|
+
- -t
|
190
|
+
- Pluggability Toolkit
|
191
|
+
require_paths:
|
192
|
+
- lib
|
193
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
194
|
+
none: false
|
195
|
+
requirements:
|
196
|
+
- - ! '>='
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
none: false
|
201
|
+
requirements:
|
202
|
+
- - ! '>='
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: '0'
|
205
|
+
requirements: []
|
206
|
+
rubyforge_project: pluggability
|
207
|
+
rubygems_version: 1.8.24
|
208
|
+
signing_key:
|
209
|
+
specification_version: 3
|
210
|
+
summary: Pluggability is a mixin module that turns an including class into a factory
|
211
|
+
for its derivatives, capable of searching for and loading them by name
|
212
|
+
test_files: []
|
metadata.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
�.�(,�����}����D�����Y�9�1�ڑ�ղ^��T1n˿���v�7�L�`!v~�<p�#�"�)Ir=�J��/����^�L]ʴW��cWO(v�<�<l8O��oո��P�����B��қ����^0C3�i�X4N��I�E���kS�������qhW���M��S���f��F?���l���,i �0�4����*������wF8Z��dI�K�.�C�Z/�Ï.1O�c�k
|