Eval versus load and plugins

I'm writing a program with a sort of plugin mechanism. Plugins are
basically single ruby files defining classes. It's not exactly a plugin
mechanism because there an only be one plugin used.

Image the program command being
  ruby myApp -plugin plugins/myPlugin.rb

I want to load the plugin which defines its own class (which follows a
certain pattern - since there are no interfaces) then instantiates it.

At the moment I'm using load to load the plugin file. I don't know the
name of the class of the specific plugin, but I assume it has a _global_
method called "new_plugin" which instantiates it.

Since I'm using load I can be sure that the latest plugin loaded will
redefine that global method to instantiate the plugin (I can't call it's
constructor directly because, again, I don't know what name the designer
is going to give the plugin class - though I can expect them to follow
the pattern of defining new_plugin)

Questions:

1. I notice that rails uses eval to load the init.rb files of plugins.
What are the advantages disadvantages of this versus using load?
(Note also this thread about using eval or load - both are suggested but
I dont see why we would use eval over load
http://www.ruby-forum.com/topic/55540#new)

2. Is there some nicer, cleaner way of doing what I'm doing without
having the plugin file define a global method?

3. Is there a neat way of forcing the plugin to match a certain pattern.
I've seen the "interface" support library, but it seems to be
shoehorning Ruby into a Java paradigm. What would be the rubyful way?
Just calling respond_to? on all of the methods I expect and raising
errors?

···

--
Posted via http://www.ruby-forum.com/.

Rover Rhubarb wrote:

I'm writing a program with a sort of plugin mechanism. Plugins are
basically single ruby files defining classes. It's not exactly a plugin
mechanism because there an only be one plugin used.

Image the program command being
  ruby myApp -plugin plugins/myPlugin.rb

I want to load the plugin which defines its own class (which follows a
certain pattern - since there are no interfaces) then instantiates it.

At the moment I'm using load to load the plugin file. I don't know the
name of the class of the specific plugin, but I assume it has a _global_
method called "new_plugin" which instantiates it.

Since I'm using load I can be sure that the latest plugin loaded will
redefine that global method to instantiate the plugin (I can't call it's
constructor directly because, again, I don't know what name the designer
is going to give the plugin class - though I can expect them to follow
the pattern of defining new_plugin)

Questions:

1. I notice that rails uses eval to load the init.rb files of plugins.
What are the advantages disadvantages of this versus using load?
(Note also this thread about using eval or load - both are suggested but
I dont see why we would use eval over load
How to evaluate file as Ruby code? - Ruby - Ruby-Forum)

Not sure off the top of my head. Someone else can probably weigh in here.

2. Is there some nicer, cleaner way of doing what I'm doing without
having the plugin file define a global method?

Make them subclass a base class that you provide, or make them mix in a module that you specify. That gives you the Class#inherited and Module#included callbacks to play with, which strikes me as cleaner than relying on a method override.

3. Is there a neat way of forcing the plugin to match a certain pattern.
I've seen the "interface" support library, but it seems to be
shoehorning Ruby into a Java paradigm. What would be the rubyful way?
Just calling respond_to? on all of the methods I expect and raising
errors?

If the plugin subclasses a base class you specify, you can either check it manually in the callback (which seems a little clumsy to me), or provide all the interface members with:

def interface_member
   raise NotImplementedError
end

in the base class. The former is probably necessary if you need to sanity check the class before doing anything with it - you can get away with the latter otherwise.

HTH

···

--
Alex

Rover Rhubarb wrote:

2. Is there some nicer, cleaner way of doing what I'm doing without
having the plugin file define a global method?

You can module_eval the file in the context of a new (anonymous, if you like) module. Here's one way to do that:

[~/tmp] cat main.rb
require 'script' # Script

plugin_module = Script.load("plugin.rb")

# either:
plugin_class = plugin_module::PluginClass
p plugin_class.new.foo

# or:
plugin_class = plugin_module.get_the_plugin_class
p plugin_class.new.foo

[~/tmp] cat plugin.rb
class PluginClass
   def foo
     "FOO"
   end
end

def get_the_plugin_class # NOT really global -- in module scope
   PluginClass
end

[~/tmp] ruby main.rb
"FOO"

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

> Questions:
>
> 1. I notice that rails uses eval to load the init.rb files of plugins.
> What are the advantages disadvantages of this versus using load?
> (Note also this thread about using eval or load - both are suggested but
> I dont see why we would use eval over load
> How to evaluate file as Ruby code? - Ruby - Ruby-Forum)
Not sure off the top of my head. Someone else can probably weigh in here.

Here's the code I think you mean:

eval(IO.read(init_path), binding, init_path)

I think the reason it does this is to allow flexible bindings. I
couldn't find "binding" defined in the method anywhere. I really don't
know, so I paraphrased this part of your question and posted it on the
Rails core list.

···

--
Giles Bowkett

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org