Pluginator

Gem Version Code Climate Coverage Status Build Status Dependency Status Documentation

Gem plugin system management, detects plugins using Gem.find_file. Is only supposed with ruby 1.9.3+ (some tests fail on 1.9.2)

Pluginator tries to stay out of your way, you do not have to include or inherit anything. Pluginator only finds and groups plugins, rest is up to you, you decide what methods to define and how to find them.

Defining plugins

create a gem with a path:

plugins/<group>/<type>/<name>.rb

with a class inside:

<group>::<type>::<name>

where <type> can be nested

Loading plugins

rvm2plugins = Pluginator.find("<group>")
type_plugins = rvm2plugins["<type>"]
types = rvm2plugins.types

Usage

Pluginator.find("<group>") => Pluginator object
plugins = Pluginator.find("<group>", type: "<type>", extends: %i{<extensions>})
plugins["<type>"] => Array of plugins
plugins.type      => Array of plugins for type defined with `type: "<type>"`
plugins.types     => Array of types
  • "<group>" - Load plugins for given group.
  • type: "<type>" - Load plugins only of given type, makes type method accessible.
  • extends: %i{<extensions>} - Extend pluginator with given extensions.

Extensions

Pluginator comes with few handful extensions.

Class exist

Check if plugin with given class name exists.

plugins = Pluginator.find("<group>", extends: %i{class_exist})
plugins.class_exist?( "<type>", "<name>") => true or false

First ask

Call a method on plugin and return first one that returns true.

plugins = Pluginator.find("<group>", extends: %i{first_ask})
plugins.first_ask( "<type>", "method_to_call", *params) => plugin or nil
plugins.first_ask!("<type>", "method_to_call", *params) => plugin or exception PluginatorError

First class

Find first plugin that class matches the given name.

plugins = Pluginator.find("<group>", extends: %i{first_class})
plugins.first_class( "<type>", "<name>") => plugin or nil
plugins.first_class!("<type>", "<name>") => plugin or exception PluginatorError

Matching

Map array of names to available plugins.

plugins = Pluginator.find("<group>", extends: %i{matching})
plugins.matching( "<type>", [<array_of_names>]) => [plugins] # nil for missing ones
plugins.matching!("<type>", [<array_of_names>]) => [plugins] or exception PluginatorError

Your own ones

You can define your own extensions for pluginator, for example:

plugins/pluginator/extensions/first_one.rb

with:

module Pluginator::Extensions
  class FirstOne
    def first_one(type)
      @plugins[type].first
    end
  end
end

And now you can use it:

plugins = Pluginator.find("<group>", extends: %i{first_one})
plugins.first_one("<type>") => first_plugin # nil when none

Exceptions

  • PluginatorError - base error for all Pluginator errors
  • MissingPlugin - raised when plugin can not be found, generated by *! methods
  • MissingType - raised when type can not be found, generated by *! methods

Examples

Example 1 - task plugins

plugins/rvm2/cli/echo.rb:

class Rvm2::Cli::Echo
  def self.question? command
    command == "echo"
  end
  def answer param
    puts param
  end
end

where question? and answer are user defined methods

Now the plugin can be used:

require 'pluginator'

rvm2plugins = Pluginator.find("rvm2")
plugin = rvm2plugins["cli"].first{ |plugin|
  plugin.question?('echo')
}
plugin.new.answer("Hello world")

Or using extensions:

require 'pluginator'

plugin = Pluginator.find("rvm2", extends: %i{first_ask}).first_ask("cli", &:question?, 'echo')
plugin.new.answer("Hello world")

Example 2 - hook plugins

plugins/rvm2/hooks/after_install/show.rb:

class Rvm2::Hooks::AfterInstall::Show
  def self.execute name, path
    puts "Ruby '#{name}' was installed in '#{path}'."
  end
end

and using hooks:

require 'pluginator'

Pluginator.find("rvm2", type: "hooks/after_install").type.each{ |plugin|
  plugin.execute(name, path)
}