Seeking design ideas for a lightweight plugin system

I’m writing a crossword format interchange app, modelled on pandoc [
GitHub - martindemello/pangrid: Crossword format conversion utility], which I’d like to do with an
“open set of plugins” architecture.

The basic idea is that the library provides a base crossword format, and
converters provide one or both of read (string → crossword) and write
(crossword → string) methods, and a description. The main program would
scan the plugin directory and know all the available readers and
writers.

So a couple of questions:

  1. It’s been a while (1.9.3) since I’ve used ruby for anything other
    than
    small scripts; is inherited hooks still the best way to do this? Or
    perhaps
    an explicit register class method, so that I don’t need to subclass
    anything just to get the hook?

  2. Some of the plugins have dependencies on other gems (e.g. axslx).
    What’s
    a good way to determine at load time whether a plugin has its
    dependencies
    met or not?

martin

On 14-03-23, 16:50, Martin DeMello wrote:

  1. It’s been a while (1.9.3) since I’ve used ruby for anything other
    than small scripts; is inherited hooks still the best way to do this? Or
    perhaps an explicit register class method, so that I don’t need to
    subclass anything just to get the hook?

  2. Some of the plugins have dependencies on other gems (e.g. axslx).
    What’s a good way to determine at load time whether a plugin has its
    dependencies met or not?

martin

Hi Martin,

I personally like the explicit register method since that gives the most
flexibility but there are many ways to do it.

If your plugins are such that they’ll generally require inheritance, you
can use that as a hook. You can also use an included hook for a module.
Including a module gives more flexibility than subclassing, leaving the
inheritance free for the user’s own code.

You could use a module namespace. Open a Plugins module as a space for
defined plugins. Any classes under this module would be exposed to your
app, via Plugins.constants.

Or use a directory. Configure a “load path” where plugins will be found.
You might still need to have the files register themselves, but provide
a place for loading them.

Some gems use a name prefix for autoloading, such as pry. Having
pry-debugger installed will autoload it, even if you just require pry.
(This can be controlled with a .pryrc file.)

The choice for how you do it will depend on how your plugins will be
written, installed, and used, and how flexible the loading/unloading
needs to be.

Andrew V.

On 14-03-23, 16:50, Martin DeMello wrote:

  1. Some of the plugins have dependencies on other gems (e.g. axslx).
    What’s a good way to determine at load time whether a plugin has its
    dependencies met or not?

martin

To answer your second question, probably the best way is to just package
them as gems, or have them provide a Gemfile that you merge with yours
(I’ve never tried this).

Andrew V.

On Mon, Mar 24, 2014 at 12:50 AM, Martin DeMello
[email protected] wrote:

  1. It’s been a while (1.9.3) since I’ve used ruby for anything other than
    small scripts; is inherited hooks still the best way to do this? Or perhaps
    an explicit register class method, so that I don’t need to subclass anything
    just to get the hook?

I don’t know what is the best way, but I’ve been looking recently into
Logstash (http://logstash.net/), which has a pluggable, and they do it
using inheritance. Maybe you could take a look at their source code
(GitHub - elastic/logstash: Logstash - transport and process your logs, events, or other data and
GitHub - elastic/logstash-contrib: THIS REPOSITORY IS NO LONGER USED. for separate
plugins)

  1. Some of the plugins have dependencies on other gems (e.g. axslx). What’s
    a good way to determine at load time whether a plugin has its dependencies
    met or not?

Maybe bundler provides some facility to manage this easily.

Jesus.

On Sun, Mar 23, 2014 at 7:47 PM, Andrew V. [email protected] wrote:

them as gems, or have them provide a Gemfile that you merge with yours
(I’ve never tried this).

Hm - no, what I’m trying to get at is some notion of optional
dependencies.
That is, I want the collection of plugins to be maintained in a single
project with the application, but not require their dependencies to be
present. The user experience would be something like

$ pangrid --list-available

Available plugins:

From:
Text
AcrossLite
PDF [disabled, missing gems: pdf-reader]

To:
Text
HTML
AcrossLite
Excel [disabled, missing gems: axslx]

martin

Thanks, logstash looks interesting! Will examine their code and see how
they do it. Examining the contrib directory they seem to both inherit
from
a base plugin class and provide a register method.

martin

On Mon, Mar 24, 2014 at 3:46 AM, Jess Gabriel y Galn <