From: Alexander Bokovoy Date: 2003-03-06T23:38:16+09:00 Subject: Re: Module#require On Thu, Mar 06, 2003 at 11:04:42PM +0900, Eugene Scripnik wrote: > Is there require method implementaion, which loads library in the > specified module context. > I want to store the classes with same name but different functionality > in one ruby process. So modules are the right thing I think. Something like this one? It has additional features like ability to load plugins from other plugins by saying 'require ""' in the plugin's code. Note <> in require's argument. Another feature is correct reporting of errors in loaded plugin (not 'Error in eval....' but 'Error in foo.rb:12345'). # ------------------------------------------------------------------------------------------ # # Plugin loader interface # (C) 2003 Alexander Bokovoy, # (C) 2003 Yuri Leikind, # The content of this file is available under GNU LGPL # module Plugin # Instantiates a new module mod_name under Plugin hierarchy which incapsulates requested plugin # code from file_name source file. def self.instantiate(mod_name, file_name) # Create new module and set a proper binding information for it # If you change the code below, adjust number of skipped lines appropriately. # Line with #{File.open("#{file_name}", "r"){|f| f.read}} is treated as 'line #1' # The third argument to module_eval must contain a negative offset of 'module #{mod_name}' # from 'line #1'. If you keep this as is, you'll see meaningful error messages which will # point to proper positions in your plugins if something wrong will happen begin mod = module_eval(<]+)>/ fmod = ::PluginLoader.registry[$1] if not (fmod.class === Module) fmod = ::PluginLoader.registry.require(amodule) end else Kernel.require amodule end end end #{File.open("#{file_name}", "r"){|f| f.read}} self end EOF rescue Exception => err log 1, "Syntax Error in plugin #{mod_name}, #{file_name}, not loading" STDERR.puts "Syntax Error in plugin #{mod_name}, #{file_name}, not loading:" STDERR.puts "#{err.message}" mod = false end return mod end end module PluginLoader class Registry < Hash def initialize(plugin_path) @plugin_path = plugin_path end def require(plugin) if plugin =~ /^<([^>]+)>/ amodule = $1 return self[amodule] if self[amodule].class === Module mod_name = amodule.to_s.gsub(/\//,"_").gsub(/\.(rb|so)/,"").capitalize @plugin_path.each do |path| [".rb", ".so", ""].each do |ext| file_name = "#{path}/#{amodule}#{ext}" if FileTest.file?(file_name) mod = ::Plugin.instantiate(mod_name, file_name) self[amodule] = mod if mod return mod end end end else Kernel.require plugin end end end class <").class === Module) result = true else result = false end end result end # Form list of loaded plugins def list_plugins PluginLoader.registry.values end end end # -------------------------------------------------------------------------------------------- -- / Alexander Bokovoy --- One does not thank logic. -- Sarek, "Journey to Babel", stardate 3842.4