I'm working on a tool that provides common functionality in a class (call it Runner) and that can invoke user-defined code using a kind of plugin system. For any execution of the tool, I need to dynamically execute various methods defined by one or more plugins. Because the Runner class defines many instance-level attributes that will be needed in the plugins, I would like to execute the plugin methods as if they were instance methods of Runner.
Here is a simplified example:
module Plugin1 def do_work p ['Plugin1', data] end end module Plugin2 def do_work p ['Plugin2', data] end end module Plugin3 def do_work p ['Plugin3', data] end end class Runner attr_accessor :data # Plugins need access to these. def initialize(data, *plugins) @data = data @plugin_names = plugins.map { |p| "Plugin#{p}" } end def run @plugin_names.each { |name| mod = Kernel.const_get(name) plugin_method = mod.instance_method(:do_work) # How do I call the plugin_method as if it were # an instance method of the Runner? } end end # Execute a runner using Plugin3 and Plugin1. r = Runner.new(987, 3, 1) r.run I have experimented with various ways to pull this off using instance_exec, bind, module_function, and so forth, but haven't gotten anything to work. I'm open to other approaches for the tool, of course, but I'm also curious whether this can be done in the manner described above.
includeing modules.