module Strelka::PluginLoader
Module API for the plugin system. This mixin adds the ability to load and install plugins into the extended object.
Attributes
The Hash of loaded plugin modules, keyed by their downcased and symbolified name (e.g., Strelka::App::Templating
=> :templating)
The prefix path for loading plugins
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
Extension callback – initialize some data structures in the extended object.
# 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
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
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
Extension callback – add instance variables to extending objects.
# 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 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 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
Install the mixin part of plugins immediately before the first instance is created.
# File lib/strelka/plugins.rb, line 249 def new( * ) self.install_plugins unless self.plugins_installed? super end
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
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 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