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.
@@ -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