module Strelka::PluginLoader

Module API for the plugin system. This mixin adds the ability to load and install plugins into the extended object.

Attributes

loaded_plugins[RW]

The Hash of loaded plugin modules, keyed by their downcased and symbolified name (e.g., Strelka::App::Templating => :templating)

plugin_path_prefix[RW]

The prefix path for loading plugins

plugins_installed_from[RW]

If plugins have already been installed, this will be the call frame they were first installed from. This is used to warn about installing plugins twice.

Public Class Methods

extended( mod ) click to toggle source

Extension callback – initialize some data structures in the extended object.

Calls superclass method
# File lib/strelka/plugins.rb, line 123
def self::extended( mod )
        super
        mod.extend( Loggability )
        mod.log_to( :strelka )
        mod.loaded_plugins = Strelka::PluginRegistry.new
        mod.plugin_path_prefix = mod.name.downcase.gsub( /::/, File::SEPARATOR )
end

Public Instance Methods

application_stack() click to toggle source

Return the list of plugin modules that are in effect for the current app.

# File lib/strelka/plugins.rb, line 288
def application_stack
        self.log.debug "Ancestors are: %p" % [ self.class.ancestors ]
        return self.ancestors.select {|mod| mod.respond_to?(:plugin_name) }
end
dump_application_stack() click to toggle source

Output the application stack into the logfile.

# File lib/strelka/plugins.rb, line 295
def dump_application_stack
        stack = self.application_stack.map( &:plugin_name )
        self.log.info "Application stack: request -> %s" % [ stack.join(" -> ") ]
end
inherited( subclass ) click to toggle source

Extension callback – add instance variables to extending objects.

Calls superclass method
# File lib/strelka/plugins.rb, line 157
def inherited( subclass )
        super
        @plugins ||= []

        subclass.loaded_plugins = self.loaded_plugins
        subclass.plugin_path_prefix = self.plugin_path_prefix
        subclass.plugins_installed_from = nil
        subclass.instance_variable_set( :@plugins, @plugins.dup )
end
install_plugins() click to toggle source

Install the mixin part of the plugin, in the order determined by the plugin registry based on the run_outside and run_inside specifications of the plugins themselves.

# File lib/strelka/plugins.rb, line 258
def install_plugins
        if self.plugins_installed?
                self.log.warn "Plugins were already installed for %p from %p" %
                        [ self, self.plugins_installed_from ]
                self.log.info "I'll attempt to install any new ones, but plugin ordering"
                self.log.info "and other functionality might exhibit strange behavior."
        else
                self.log.info "Installing plugins for %p." % [ self ]
        end

        sorted_plugins = self.loaded_plugins.tsort.reverse

        sorted_plugins.each do |name|
                mod = self.loaded_plugins[ name ]

                unless @plugins.include?( name ) || @plugins.include?( mod )
                        self.log.debug "  skipping %s" % [ name ]
                        next
                end

                self.log.info "  including %p in %p." % [ mod, self ]
                include( mod )
        end

        self.plugins_installed_from = caller( 1 ).first
end
load_plugin( name ) click to toggle source

Load the plugin with the given name

# File lib/strelka/plugins.rb, line 196
def load_plugin( name )

        # Just return Modules as-is
        return name if name.is_a?( Strelka::Plugin )
        mod = self.loaded_plugins[ name.to_sym ]

        unless mod.is_a?( Module )
                pluginpath = File.join( self.plugin_path_prefix, name.to_s )
                require( pluginpath )
                mod = self.loaded_plugins[ name.to_sym ] or
                        raise "#{name} plugin didn't load correctly."
        end

        return mod
end
new( * ) click to toggle source

Install the mixin part of plugins immediately before the first instance is created.

Calls superclass method
# File lib/strelka/plugins.rb, line 249
def new( * )
        self.install_plugins unless self.plugins_installed?
        super
end
plugin( *names, &block )
Alias for: plugins
plugins( *names, &block ) click to toggle source

Load the plugins with the given names and install them.

# File lib/strelka/plugins.rb, line 169
def plugins( *names, &block )
        self.log.info "Adding plugins: %s" % [ names.flatten.map(&:to_s).join(', ') ]

        # Load the associated Plugin Module objects
        names.flatten.each {|name| self.load_plugin(name) }

        # Add the name/s to the list of mixins to apply on startup
        @plugins |= names

        # Install the declarative half of the plugin immediately
        names.each do |name|
                plugin = nil

                if name.is_a?( Module )
                        plugin = name
                else
                        plugin = self.loaded_plugins[ name ]
                end

                self.log.debug "  registering %p" % [ name ]
                self.register_plugin( plugin, &block )
        end
end
Also aliased as: plugin
plugins_installed?() click to toggle source

Returns true if the plugins for the extended app class have already been installed.

# File lib/strelka/plugins.rb, line 151
def plugins_installed?
        return !self.plugins_installed_from.nil?
end
register_plugin( mod, &block ) click to toggle source

Register the plugin mod in the receiving class. This adds any declaratives and class-level data necessary for configuring the plugin.

# File lib/strelka/plugins.rb, line 216
def register_plugin( mod, &block )
        if mod.const_defined?( :ClassMethods )
                cm_mod = mod.const_get(:ClassMethods)
                self.log.debug "  adding class methods from %p" % [ cm_mod ]

                extend( cm_mod )
                cm_mod.instance_variables.each do |ivar|
                        next if instance_variable_defined?( ivar )

                        ival = cm_mod.instance_variable_get( ivar )
                        copy = Strelka::DataUtilities.deep_copy( ival )

                        self.log.debug "  copying class instance variable %s (%p)" % [ ivar, copy ]

                        instance_variable_set( ivar, copy )
                        self.log.debug "  instance variable %p set to %p in %p" %
                                [ ivar, self.instance_variable_get(ivar), self ]
                end
        end

        if block
                if mod.respond_to?( :configure_block )
                        mod.configure_block( self, &block )
                else
                        self.log.warn "Blocked passed to %p, which doesn't support block config." %
                                [ mod ]
                end
        end
end