Module::Pluggable::Plugins (Class)
# File lib/module/pluggable.rb, line 54
54: def initialize(opts)
55: @opts = opts
56: @dir = Pathname.new(opts[:search_path])
57: @plugins = {}
58: reload
59: end
Get instance of klass_name plugin.
# File lib/module/pluggable.rb, line 99
99: def [](klass_name)
100: @plugins[klass_name][:instance] if @plugins.key?(klass_name)
101: end
Call name method of each plugins with args and returns Hash of the result and its plugin name.
# File lib/module/pluggable.rb, line 153
153: def call(name, *args)
154: ret = {}
155: each do |k,v|
156: ret[k] = v.send(name, *args) if v.respond_to?(name)
157: end
158: ret
159: end
Iterates with plugin name and its instance.
# File lib/module/pluggable.rb, line 145
145: def each(&block)
146: @plugins.each do |k,v|
147: yield k, v[:instance]
148: end
149: end
Unload all plugins and reload it.
# File lib/module/pluggable.rb, line 138
138: def force_reload
139: call(:on_unload)
140: @plugins.clear
141: reload
142: end
Load klass_name. The plugin is loaded in anonymous module not order to destroy the environments. And remember loaded time for reloading.
plugin filename must be interconversion with its class name. In this class, the conversion is do with +file2klass+/+klass2file+ methods.
# File lib/module/pluggable.rb, line 68
68: def load(klass_name)
69: return if @plugins.include?(klass_name)
70:
71: filename = klass2file(klass_name)
72:
73: mod = Module.new
74: mod.module_eval(File.open("#{@opts[:search_path]}/#{filename}.rb") {|f| f.read}, filename)
75:
76: c = nil
77: begin
78: c = mod.const_get(klass_name)
79: rescue NameError
80: raise ClassNotFoundError.new("#{@opts[:search_path]}/#{filename} must include #{klass_name} class")
81: end
82:
83: if !@opts[:base_class] || c < @opts[:base_class]
84: @plugins[klass_name] = {
85: :instance => c.new,
86: :loaded => Time.now,
87: }
88: else
89: raise NotInheritAbstractClassError.new("The class #{klass_name} must inherit #{@opts[:base_class]}")
90: end
91:
92: @plugins[klass_name][:instance].on_load rescue NameError
93: @plugins[klass_name][:instance].instance_variable_set(:@plugins, self)
94:
95: klass_name
96: end
Undefined methods are delegated to each plugins. This is alias of call
# File lib/module/pluggable.rb, line 163
163: def method_missing(name, *args)
164: call(name, *args)
165: end
Reload klass_name or load unloaded plugins or reload modified plugins. returns [loaded, unloaded]
# File lib/module/pluggable.rb, line 115
115: def reload(klass_name=nil)
116: if klass_name
117: unload(klass_name)
118: load(klass_name)
119: klass_name
120: else
121: loaded = []
122: unloaded = []
123: Dir.glob("#{@opts[:search_path]}/*.rb") do |f|
124: klass_name = file2klass(File.basename(f, ".rb").sub(/^\d+/, ""))
125: if @plugins.include?(klass_name)
126: if File.mtime(f) > @plugins[klass_name][:loaded]
127: loaded << reload(klass_name)
128: end
129: else
130: loaded << reload(klass_name)
131: end
132: end
133: [loaded, unloaded]
134: end
135: end
Unload +klass_name
# File lib/module/pluggable.rb, line 104
104: def unload(klass_name)
105: if @plugins.key?(klass_name)
106: @plugins[klass_name][:instance].on_unload rescue NameError
107: @plugins.delete(klass_name)
108: end
109: end