module-pluggable 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/Changelog +8 -0
- data/README +41 -0
- data/Rakefile +144 -0
- data/examples/plugins/hoge_hoge.rb +10 -0
- data/examples/plugins/test.rb +10 -0
- data/examples/simple.rb +36 -0
- data/lib/module/pluggable.rb +182 -0
- data/test/module-pluggable_test.rb +88 -0
- data/test/plugins/test.rb +10 -0
- data/test/test_helper.rb +2 -0
- metadata +67 -0
data/Changelog
ADDED
data/README
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
= README for module-pluggable
|
2
|
+
|
3
|
+
module-pluggable provides plugin system for classes.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
=== Archive Installation
|
8
|
+
|
9
|
+
rake install
|
10
|
+
|
11
|
+
=== Gem Installation
|
12
|
+
|
13
|
+
gem install module-pluggable
|
14
|
+
|
15
|
+
=== Subversion Repository
|
16
|
+
|
17
|
+
Hosted by CodeRepos[http://coderepos.org/share/browser/lang/ruby/module-pluggable]
|
18
|
+
|
19
|
+
svn co http://svn.coderepos.org/share/lang/ruby/module-pluggable/
|
20
|
+
|
21
|
+
== Examples
|
22
|
+
|
23
|
+
class APluggableClass
|
24
|
+
pluggable :plugins
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
plugins.init(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def say
|
31
|
+
plugins.say("hello")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
see examples/simple.rb.
|
36
|
+
|
37
|
+
== Copyright
|
38
|
+
|
39
|
+
Author:: cho45 <cho45@lowreal.net>
|
40
|
+
Copyright:: Copyright (c) 2007 cho45 www.lowreal.net
|
41
|
+
License:: Ruby's
|
data/Rakefile
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/contrib/rubyforgepublisher'
|
9
|
+
require 'rubyforge'
|
10
|
+
require 'fileutils'
|
11
|
+
include FileUtils
|
12
|
+
|
13
|
+
AUTHOR = "cho45"
|
14
|
+
EMAIL = "cho45@lowreal.net"
|
15
|
+
DESCRIPTION = ""
|
16
|
+
RUBYFORGE_PROJECT = "modulepluggable"
|
17
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
18
|
+
BIN_FILES = %w( )
|
19
|
+
VERS = "0.0.1"
|
20
|
+
|
21
|
+
|
22
|
+
NAME = "module-pluggable"
|
23
|
+
REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
24
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
25
|
+
RDOC_OPTS = ['--quiet', '--title', "#{NAME} documentation",
|
26
|
+
"--charset", "utf-8",
|
27
|
+
"--opname", "index.html",
|
28
|
+
"--line-numbers",
|
29
|
+
"--main", "README",
|
30
|
+
"--inline-source"]
|
31
|
+
|
32
|
+
desc "Packages up #{NAME} gem."
|
33
|
+
task :default => [:test]
|
34
|
+
task :package => [:clean]
|
35
|
+
|
36
|
+
Rake::TestTask.new("test") { |t|
|
37
|
+
t.libs << "test"
|
38
|
+
t.pattern = "test/**/*_test.rb"
|
39
|
+
t.verbose = true
|
40
|
+
}
|
41
|
+
|
42
|
+
spec = Gem::Specification.new do |s|
|
43
|
+
s.name = NAME
|
44
|
+
s.version = VERS
|
45
|
+
s.platform = Gem::Platform::RUBY
|
46
|
+
s.has_rdoc = true
|
47
|
+
s.extra_rdoc_files = ["README", "Changelog"]
|
48
|
+
s.rdoc_options += RDOC_OPTS + ['--exclude', '^(extras)/']
|
49
|
+
s.summary = DESCRIPTION
|
50
|
+
s.description = DESCRIPTION
|
51
|
+
s.author = AUTHOR
|
52
|
+
s.email = EMAIL
|
53
|
+
s.homepage = HOMEPATH
|
54
|
+
s.executables = BIN_FILES
|
55
|
+
s.rubyforge_project = RUBYFORGE_PROJECT
|
56
|
+
s.bindir = "bin"
|
57
|
+
s.require_path = "lib"
|
58
|
+
#s.autorequire = "safe_eval"
|
59
|
+
s.test_files = Dir["test/test_*.rb"]
|
60
|
+
|
61
|
+
#s.add_dependency('activesupport', '>=1.3.1')
|
62
|
+
#s.required_ruby_version = '>= 1.8.2'
|
63
|
+
|
64
|
+
s.files = %w(README Changelog Rakefile) +
|
65
|
+
Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
|
66
|
+
Dir.glob("ext/**/*.{h,c,rb}") +
|
67
|
+
Dir.glob("examples/**/*.rb") +
|
68
|
+
Dir.glob("tools/*.rb")
|
69
|
+
|
70
|
+
s.extensions = FileList["ext/**/extconf.rb"].to_a
|
71
|
+
end
|
72
|
+
|
73
|
+
Rake::GemPackageTask.new(spec) do |p|
|
74
|
+
p.need_tar = true
|
75
|
+
p.gem_spec = spec
|
76
|
+
end
|
77
|
+
|
78
|
+
task :install do
|
79
|
+
name = "#{NAME}-#{VERS}.gem"
|
80
|
+
sh %{rake package}
|
81
|
+
sh %{sudo gem install pkg/#{name}}
|
82
|
+
end
|
83
|
+
|
84
|
+
task :uninstall => [:clean] do
|
85
|
+
sh %{sudo gem uninstall #{NAME}}
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
Rake::RDocTask.new do |rdoc|
|
90
|
+
rdoc.rdoc_dir = 'html'
|
91
|
+
rdoc.options += RDOC_OPTS
|
92
|
+
rdoc.template = "#{ENV["HOME"]}/coderepos/lang/ruby/rdoc/generators/template/html/resh/resh.rb"
|
93
|
+
#rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
94
|
+
if ENV['DOC_FILES']
|
95
|
+
rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
|
96
|
+
else
|
97
|
+
rdoc.rdoc_files.include('README', 'Changelog')
|
98
|
+
rdoc.rdoc_files.include('examples/simple.rb')
|
99
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
100
|
+
rdoc.rdoc_files.include('ext/**/*.c')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "Publish to RubyForge"
|
105
|
+
task :rubyforge => [:rdoc, :package] do
|
106
|
+
Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'cho45').upload
|
107
|
+
end
|
108
|
+
|
109
|
+
desc "Publish to lab"
|
110
|
+
task :publab do
|
111
|
+
require 'rake/contrib/sshpublisher'
|
112
|
+
|
113
|
+
path = File.expand_path(File.dirname(__FILE__))
|
114
|
+
|
115
|
+
Rake::SshDirPublisher.new(
|
116
|
+
"cho45@lab.lowreal.net",
|
117
|
+
"/srv/www/lab.lowreal.net/public/site-ruby",
|
118
|
+
path + "/pkg"
|
119
|
+
).upload
|
120
|
+
end
|
121
|
+
|
122
|
+
desc 'Package and upload the release to rubyforge.'
|
123
|
+
task :release => [:clean, :package] do |t|
|
124
|
+
v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
|
125
|
+
abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
|
126
|
+
pkg = "pkg/#{NAME}-#{VERS}"
|
127
|
+
|
128
|
+
rf = RubyForge.new
|
129
|
+
puts "Logging in"
|
130
|
+
rf.login
|
131
|
+
|
132
|
+
c = rf.userconfig
|
133
|
+
# c["release_notes"] = description if description
|
134
|
+
# c["release_changes"] = changes if changes
|
135
|
+
c["preformatted"] = true
|
136
|
+
|
137
|
+
files = [
|
138
|
+
"#{pkg}.tgz",
|
139
|
+
"#{pkg}.gem"
|
140
|
+
].compact
|
141
|
+
|
142
|
+
puts "Releasing #{NAME} v. #{VERS}"
|
143
|
+
rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
|
144
|
+
end
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!ruby -I../lib simple.rb
|
2
|
+
|
3
|
+
require "module/pluggable"
|
4
|
+
|
5
|
+
module Example
|
6
|
+
|
7
|
+
class SimplePluggable
|
8
|
+
# pluggable [name=:plugins] [opts]
|
9
|
+
# pluggable make the name of instance method
|
10
|
+
# returning instance of Module::Pluggable::Plugin.
|
11
|
+
#
|
12
|
+
# All loaded plugins are in anonymous module,
|
13
|
+
# so you can't access the classes directly,
|
14
|
+
# and you can create some plugin-sets
|
15
|
+
# without confusing class variables etc.
|
16
|
+
pluggable
|
17
|
+
|
18
|
+
# plugins.init(self)
|
19
|
+
#
|
20
|
+
# `init' method is not defined on Module::Pluggable::Plugin.
|
21
|
+
# undefined methods are delegated to `call' the plugins.
|
22
|
+
# In this case, `plugins.init(self)' is same as `plugins.call(:init, self)'.
|
23
|
+
def initialize
|
24
|
+
plugins.init(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def say
|
28
|
+
plugins.each do |name, instance|
|
29
|
+
puts instance.say
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
Example::SimplePluggable.new.say
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# Author:: cho45 <cho45@lowreal.net>
|
2
|
+
# Copyright:: copyright (c) 2007 cho45 www.lowreal.net
|
3
|
+
# License:: Ruby's
|
4
|
+
|
5
|
+
require "pathname"
|
6
|
+
|
7
|
+
module Module::Pluggable
|
8
|
+
DEFAULT_OPTS = {
|
9
|
+
:search_path => "plugins",
|
10
|
+
:except => /_$/,
|
11
|
+
:base_class => nil,
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
# pluggable make the name of instance method
|
15
|
+
# returning instance of Module::Pluggable::Plugin.
|
16
|
+
#
|
17
|
+
# All loaded plugins are in anonymous module,
|
18
|
+
# so you can't access the classes directly,
|
19
|
+
# and you can create some plugin-sets
|
20
|
+
# without confusing class variables etc.
|
21
|
+
#
|
22
|
+
# opts => {
|
23
|
+
# :search_path => name,
|
24
|
+
# :base_class => nil,
|
25
|
+
# :except => /_$/, # not yet
|
26
|
+
# }
|
27
|
+
def pluggable(name=:plugins, o={})
|
28
|
+
opts = DEFAULT_OPTS.merge(o)
|
29
|
+
opts[:search_path] = name ? name.to_s : opts[:name].to_s unless opts[:search_path]
|
30
|
+
|
31
|
+
class_eval <<-EOS
|
32
|
+
def #{name}
|
33
|
+
@#{name} ||= Module::Pluggable::Plugins.new(@@pluggable_opts[:#{name}])
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.set_pluggable_opts(name, opts)
|
37
|
+
(@@pluggable_opts ||= {})[name] = opts
|
38
|
+
end
|
39
|
+
EOS
|
40
|
+
self.set_pluggable_opts(name, opts)
|
41
|
+
(class << self; self; end).instance_eval do
|
42
|
+
remove_method(:set_pluggable_opts)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Plugins
|
47
|
+
include Enumerable
|
48
|
+
|
49
|
+
class PluginsError < StandardError; end
|
50
|
+
class ClassNotFoundError < PluginsError; end
|
51
|
+
class NotInheritAbstractClassError < PluginsError; end
|
52
|
+
|
53
|
+
def initialize(opts)
|
54
|
+
@opts = opts
|
55
|
+
@dir = Pathname.new(opts[:search_path])
|
56
|
+
@plugins = {}
|
57
|
+
reload
|
58
|
+
end
|
59
|
+
|
60
|
+
# Load +klass_name+.
|
61
|
+
# The plugin is loaded in anonymous module not order to
|
62
|
+
# destroy the environments.
|
63
|
+
# And remember loaded time for reloading.
|
64
|
+
#
|
65
|
+
# plugin filename must be interconversion with its class name.
|
66
|
+
# In this class, the conversion is do with +file2klass+/+klass2file+ methods.
|
67
|
+
def load(klass_name)
|
68
|
+
return if @plugins.include?(klass_name)
|
69
|
+
|
70
|
+
filename = klass2file(klass_name)
|
71
|
+
|
72
|
+
mod = Module.new
|
73
|
+
mod.module_eval(File.open("#{@opts[:search_path]}/#{filename}.rb") {|f| f.read}, filename)
|
74
|
+
|
75
|
+
c = nil
|
76
|
+
begin
|
77
|
+
c = mod.const_get(klass_name)
|
78
|
+
rescue NameError
|
79
|
+
raise ClassNotFoundError.new("#{@opts[:search_path]}/#{filename} must include #{klass_name} class")
|
80
|
+
end
|
81
|
+
|
82
|
+
if !@opts[:base_class] || c < @opts[:base_class]
|
83
|
+
@plugins[klass_name] = {
|
84
|
+
:instance => c.new,
|
85
|
+
:loaded => Time.now,
|
86
|
+
}
|
87
|
+
else
|
88
|
+
raise NotInheritAbstractClassError.new("The class #{klass_name} must inherit #{@opts[:base_class]}")
|
89
|
+
end
|
90
|
+
|
91
|
+
@plugins[klass_name][:instance].on_load rescue NameError
|
92
|
+
@plugins[klass_name][:instance].instance_variable_set(:@plugins, self)
|
93
|
+
|
94
|
+
klass_name
|
95
|
+
end
|
96
|
+
|
97
|
+
# Get instance of +klass_name+ plugin.
|
98
|
+
def [](klass_name)
|
99
|
+
@plugins[klass_name][:instance] if @plugins.key?(klass_name)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Unload +klass_name
|
103
|
+
def unload(klass_name)
|
104
|
+
if @plugins.key?(klass_name)
|
105
|
+
@plugins[klass_name][:instance].on_unload rescue NameError
|
106
|
+
@plugins.delete(klass_name)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Reload +klass_name+ or
|
111
|
+
# load unloaded plugins or
|
112
|
+
# reload modified plugins.
|
113
|
+
# returns [loaded, unloaded]
|
114
|
+
def reload(klass_name=nil)
|
115
|
+
if klass_name
|
116
|
+
unload(klass_name)
|
117
|
+
load(klass_name)
|
118
|
+
klass_name
|
119
|
+
else
|
120
|
+
loaded = []
|
121
|
+
unloaded = []
|
122
|
+
Dir.glob("#{@opts[:search_path]}/*.rb") do |f|
|
123
|
+
klass_name = file2klass(File.basename(f, ".rb").sub(/^\d+/, ""))
|
124
|
+
if @plugins.include?(klass_name)
|
125
|
+
if File.mtime(f) > @plugins[klass_name][:loaded]
|
126
|
+
loaded << reload(klass_name)
|
127
|
+
end
|
128
|
+
else
|
129
|
+
loaded << reload(klass_name)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
[loaded, unloaded]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Unload all plugins and reload it.
|
137
|
+
def force_reload
|
138
|
+
call(:on_unload)
|
139
|
+
@plugins.clear
|
140
|
+
reload
|
141
|
+
end
|
142
|
+
|
143
|
+
# Iterates with plugin name and its instance.
|
144
|
+
def each(&block)
|
145
|
+
@plugins.each do |k,v|
|
146
|
+
yield k, v[:instance]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Call +name+ method of each plugins with +args+
|
151
|
+
# and returns Hash of the result and its plugin name.
|
152
|
+
def call(name, *args)
|
153
|
+
ret = {}
|
154
|
+
each do |k,v|
|
155
|
+
ret[k] = v.send(name, *args) if v.respond_to?(name)
|
156
|
+
end
|
157
|
+
ret
|
158
|
+
end
|
159
|
+
|
160
|
+
# Undefined methods are delegated to each plugins.
|
161
|
+
# This is alias of +call+
|
162
|
+
def method_missing(name, *args)
|
163
|
+
call(name, *args)
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
# convert foo/foo_bar to Foo::FooBar
|
168
|
+
def file2klass(str)
|
169
|
+
str.split("/").map {|c|
|
170
|
+
c.split(/_/).collect {|i| i.capitalize }.join("")
|
171
|
+
}.join("::")
|
172
|
+
end
|
173
|
+
|
174
|
+
# convert Foo::FooBar to foo/foo_bar
|
175
|
+
def klass2file(str)
|
176
|
+
str.split(/::/).map {|c|
|
177
|
+
c.scan(/[A-Z][a-z0-9]*/).join("_").downcase
|
178
|
+
}.join("/")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
Class.instance_eval { include Module::Pluggable }
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
require "pathname"
|
3
|
+
require "tmpdir"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
class TestModulePluggable < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@dir = Pathname.new(Dir.tmpdir) + "#{File.basename($0)}.#$$.#{rand(0xffffff)}"
|
9
|
+
@dir.mkpath
|
10
|
+
@test_dir = Pathname.new(File.dirname(__FILE__))
|
11
|
+
FileUtils.cp_r(@test_dir + "plugins", @dir)
|
12
|
+
@plugins_dir = @dir + "plugins"
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
@dir.rmtree
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_classname_conversion
|
20
|
+
m = Module::Pluggable::Plugins.new({:search_path => @plugins_dir})
|
21
|
+
assert_equal "foo_bar", m.__send__(:klass2file, "FooBar")
|
22
|
+
assert_equal "FooBar", m.__send__(:file2klass, "foo_bar")
|
23
|
+
assert_equal "foo/foo_bar", m.__send__(:klass2file, "Foo::FooBar")
|
24
|
+
assert_equal "Foo::FooBar", m.__send__(:file2klass, "foo/foo_bar")
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_success
|
28
|
+
path = @plugins_dir
|
29
|
+
test = Class.new {
|
30
|
+
pluggable :plugins, :search_path => path
|
31
|
+
}.new
|
32
|
+
assert test.plugins["Test"]
|
33
|
+
assert_equal "This is test plugin.", test.plugins.call(:description)["Test"]
|
34
|
+
|
35
|
+
obj = Object.new
|
36
|
+
test.plugins.call(:instance_variable_set, :@test_obj, obj)
|
37
|
+
assert_equal obj, test.plugins["Test"].instance_variable_get(:@test_obj)
|
38
|
+
assert_equal test.plugins, test.plugins["Test"].foobar
|
39
|
+
|
40
|
+
assert_equal "This is test plugin.", test.plugins.description["Test"]
|
41
|
+
|
42
|
+
# inherit test
|
43
|
+
test = Class.new(test.class).new
|
44
|
+
assert test.plugins["Test"]
|
45
|
+
assert_equal "This is test plugin.", test.plugins.call(:description)["Test"]
|
46
|
+
|
47
|
+
test = Class.new {
|
48
|
+
pluggable :plugins, :search_path => "'"
|
49
|
+
}.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_multi
|
53
|
+
path = @plugins_dir
|
54
|
+
test = Class.new {
|
55
|
+
pluggable :plugins, :search_path => path
|
56
|
+
pluggable :filters, :search_path => path
|
57
|
+
}.new
|
58
|
+
assert test.plugins["Test"]
|
59
|
+
assert_equal "This is test plugin.", test.plugins.call(:description)["Test"]
|
60
|
+
assert test.filters["Test"]
|
61
|
+
assert_equal "This is test plugin.", test.filters.call(:description)["Test"]
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_inherit
|
65
|
+
path = @plugins_dir
|
66
|
+
assert_raise(Module::Pluggable::Plugins::NotInheritAbstractClassError) do
|
67
|
+
test = Class.new {
|
68
|
+
pluggable :plugins, :search_path => path, :base_class => PluginBase
|
69
|
+
}.new
|
70
|
+
test.plugins
|
71
|
+
end
|
72
|
+
|
73
|
+
testpl = path + "test.rb"
|
74
|
+
n = testpl.read.sub(/class Test/, "class Test < TestModulePluggable::PluginBase")
|
75
|
+
testpl.open("w") {|f| f.puts n }
|
76
|
+
|
77
|
+
assert_nothing_raised do
|
78
|
+
test = Class.new {
|
79
|
+
pluggable :plugins, :search_path => path, :base_class => PluginBase
|
80
|
+
}.new
|
81
|
+
test.plugins
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class PluginBase
|
86
|
+
# Nice boat.
|
87
|
+
end
|
88
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: module-pluggable
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-10-06 00:00:00 +09:00
|
8
|
+
summary: ''
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: cho45@lowreal.net
|
12
|
+
homepage: http://modulepluggable.rubyforge.org
|
13
|
+
rubyforge_project: modulepluggable
|
14
|
+
description: ''
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
post_install_message:
|
30
|
+
authors:
|
31
|
+
- cho45
|
32
|
+
files:
|
33
|
+
- README
|
34
|
+
- Changelog
|
35
|
+
- Rakefile
|
36
|
+
- test/module-pluggable_test.rb
|
37
|
+
- test/plugins
|
38
|
+
- test/test_helper.rb
|
39
|
+
- test/plugins/test.rb
|
40
|
+
- lib/module
|
41
|
+
- lib/module/pluggable.rb
|
42
|
+
- examples/simple.rb
|
43
|
+
- examples/plugins/hoge_hoge.rb
|
44
|
+
- examples/plugins/test.rb
|
45
|
+
test_files:
|
46
|
+
- test/test_helper.rb
|
47
|
+
rdoc_options:
|
48
|
+
- "--quiet"
|
49
|
+
- "--title"
|
50
|
+
- module-pluggable documentation
|
51
|
+
- "--charset"
|
52
|
+
- utf-8
|
53
|
+
- "--opname"
|
54
|
+
- index.html
|
55
|
+
- "--line-numbers"
|
56
|
+
- "--main"
|
57
|
+
- README
|
58
|
+
- "--inline-source"
|
59
|
+
- "--exclude"
|
60
|
+
- "^(extras)/"
|
61
|
+
extra_rdoc_files:
|
62
|
+
- README
|
63
|
+
- Changelog
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
requirements: []
|
67
|
+
dependencies: []
|