Class: GemPlugin::Manager

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/gem_plugin.rb

Overview

This class is used by people who use gem plugins (but don’t necessarily make them) to add plugins to their own systems. It provides a way to load plugins, list them, and create them as needed.

It is a singleton so you use like this: GemPlugins::Manager.instance.load

Instance Method Summary collapse

Constructor Details

#initializeManager

Returns a new instance of Manager.



63
64
65
66
# File 'lib/gem_plugin.rb', line 63

def initialize
  @plugins = {}
  @loaded_gems = []
end

Instance Method Details

#availableObject

Returns a map of URIs->=> Plugin that you can use to investigate available handlers.



151
152
153
# File 'lib/gem_plugin.rb', line 151

def available
  return @plugins
end

#create(name, options = {}) ⇒ Object

Resolves the given name (should include /category/name) to find the plugin class and create an instance. You can pass a second hash option that is then given to the Plugin to configure it.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/gem_plugin.rb', line 133

def create(name, options = {})
  last_slash = name.rindex("/")
  category = name[0 ... last_slash]
  plugin = name[last_slash .. -1]

  map = @plugins[category]
  if not map
    raise "Plugin category #{category} does not exist"
  elsif not map.has_key? plugin
    raise "Plugin #{plugin} does not exist in category #{category}"
  else
    map[plugin].new(options)
  end
end

#load(needs = {}) ⇒ Object

Responsible for going through the list of available gems and loading any plugins requested. It keeps track of what it’s loaded already and won’t load them again.

It accepts one parameter which is a hash of gem depends that should include or exclude a gem from being loaded. A gem must depend on gem_plugin to be considered, but then each system has to add it’s own INCLUDE to make sure that only plugins related to it are loaded.

An example again comes from Mongrel. In order to load all Mongrel plugins:

GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE

Which will load all plugins that depend on mongrel AND gem_plugin. Now, one extra thing we do is we delay loading Rails Mongrel plugins until after rails is configured. Do do this the mongrel_rails script has:

GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE

The only thing to remember is that this is saying “include a plugin if it depends on gem_plugin, mongrel, but NOT rails”. If a plugin also depends on other stuff then it’s loaded just fine. Only gem_plugin, mongrel, and rails are ever used to determine if it should be included.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/gem_plugin.rb', line 91

def load(needs = {})
  sdir = File.join(Gem.dir, "specifications")
  gems = Gem::SourceIndex.from_installed_gems(sdir)
  needs = needs.merge({"gem_plugin" => INCLUDE})

  gems.each do |path, gem|
    # don't load gems more than once
    next if @loaded_gems.include? gem.name        
    check = needs.dup

    # rolls through the depends and inverts anything it finds
    gem.dependencies.each do |dep|
      # this will fail if a gem is depended more than once
      if check.has_key? dep.name
        check[dep.name] = !check[dep.name]
      end
    end
    
    # now since excluded gems start as true, inverting them
    # makes them false so we'll skip this gem if any excludes are found
    if (check.select {|name,test| !test}).length == 0
      # looks like no needs were set to false, so it's good
      require_gem gem.name
      @loaded_gems << gem.name
    end

  end
end

#register(category, name, klass) ⇒ Object

Not necessary for you to call directly, but this is how GemPlugin::Base.inherited actually adds a plugin to a category.



124
125
126
127
# File 'lib/gem_plugin.rb', line 124

def register(category, name, klass)
  @plugins[category] ||= {}
  @plugins[category][name.downcase] = klass
end