File: lib/radiant/extension_loader.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Radiant#5
  class: ExtensionLoader#6
includes
  Simpleton   
inherits from
  Object ( Builtin-Module )
has properties
attribute: initializer [RW] #32
attribute: extensions [RW] #32
method: initialize #34
method: enabled_extension_paths #40
method: paths / 1 #54
method: load_extensions #63
method: load_extension / 1 #71
method: load_extension_initalizers #87
method: deactivate_extensions #93
method: activate_extensions #100
alias: reactivate activate_extensions #105
class method: record_path / 2 #113
  class: DependenciesObserver#10
inherits from
  MethodObserver   
has properties
attribute: config [RW] #14
method: initialize / 1 #16
method: before_clear / 1 #20
method: after_clear / 1 #24

Code

   1  require 'radiant/extension'
   2  require 'radiant/extension_path'
   3  require 'method_observer'
   4 
   5  module Radiant
   6    class ExtensionLoader
   7      # The ExtensionLoader is reponsible for the loading, activation and reactivation of extensions. 
   8      # The noticing of important subdirectories is now handled by the ExtensionPath class.
   9 
  10      class DependenciesObserver < MethodObserver
  11        # Extends the reload mechanism in ActiveSupport so that extensions are deactivated and reactivated
  12        # when model classes are reloaded (in development mode, usually).
  13        
  14        attr_accessor :config
  15 
  16        def initialize(rails_config) #:nodoc
  17          @config = rails_config
  18        end
  19 
  20        def before_clear(*args) #:nodoc
  21          ExtensionLoader.deactivate_extensions
  22        end
  23 
  24        def after_clear(*args) #:nodoc
  25          ExtensionLoader.load_extensions
  26          ExtensionLoader.activate_extensions
  27        end
  28      end
  29 
  30      include Simpleton
  31 
  32      attr_accessor :initializer, :extensions
  33 
  34      def initialize #:nodoc
  35        self.extensions = []
  36      end
  37 
  38      # Returns a list of paths to all the extensions that are enabled in the configuration of this application.
  39      #
  40      def enabled_extension_paths
  41        ExtensionPath.enabled.map(&:to_s)
  42      end
  43 
  44      # Returns a list of all the paths discovered within extension roots of the specified type.
  45      # (by calling the corresponding class method on ExtensionPath).
  46      #
  47      #   extension_loader.paths(:metal)         #=> ['extension/app/metal', 'extension/app/metal']
  48      #   extension_loader.paths(:controller)    #=> ['extension/app/controllers', 'extension/app/controllers']
  49      #   extension_loader.paths(:eager_load)    #=> ['extension/app/controllers', 'extension/app/models', 'extension/app/helpers']
  50      #
  51      # For compatibility with the old loader, there are corresponding +type_paths+ methods.
  52      # There are also (deprecated) +add_type_paths+ methods. 
  53      #
  54      def paths(type)
  55        ExtensionPath.send("#{type}_paths".to_sym)
  56      end
  57 
  58      # Loads but does not activate all the extensions that have been enabled, in the configured order 
  59      # (which defaults to alphabetically). If an extension fails to load an error will be logged
  60      # but application startup will continue. If an extension doesn't exist, a LoadError will be raised
  61      # and startup will halt.
  62      #
  63      def load_extensions
  64        configuration = initializer.configuration
  65        @observer ||= DependenciesObserver.new(configuration).observe(::ActiveSupport::Dependencies)
  66        self.extensions = configuration.enabled_extensions.map { |ext| load_extension(ext) }.compact
  67      end
  68      
  69      # Loads the specified extension.
  70      #
  71      def load_extension(name)
  72        extension_path = ExtensionPath.find(name)
  73        begin
  74          constant = "#{name}_extension".camelize
  75          extension = constant.constantize
  76          extension.unloadable
  77          extension.path = extension_path
  78          extension
  79        rescue LoadError, NameError => e
  80          $stderr.puts "Could not load extension: #{name}.\n#{e.inspect}"
  81          nil
  82        end
  83      end
  84      
  85      # Loads all the initializers defined in enabled extensions, in the configured order.
  86      #
  87      def load_extension_initalizers
  88        extensions.each &:load_initializers
  89      end
  90 
  91      # Deactivates all enabled extensions.
  92      #
  93      def deactivate_extensions
  94        extensions.each &:deactivate
  95      end
  96 
  97      # Activates all enabled extensions and makes sure that any newly declared subclasses of Page are recognised.
  98      # The admin UI and views have to be reinitialized each time to pick up changes and avoid duplicates.
  99      #
 100      def activate_extensions
 101        initializer.initialize_views
 102        extensions.each &:activate
 103        Page.load_subclasses
 104      end
 105      alias :reactivate :activate_extensions
 106 
 107      class << self
 108        # Builds an ExtensionPath object from the supplied path, working out the name of the extension on the way.
 109        # The ExtensionPath object will later be used to scan and load the extension.
 110        # An extension name can be supplied in addition to the path. It will be processed in the usual way to 
 111        # remove radiant- and -extension and any verion numbering.
 112        #
 113        def record_path(path, name=nil)
 114          ExtensionPath.from_path(path, name)
 115        end
 116      
 117        # For compatibility with old calls probably still to be found in some extensions.
 118        #
 119        %w{controller model view metal plugin load locale}.each do |type|
 120          define_method("#{type}_paths".to_sym) do
 121            paths(type)
 122          end
 123          define_method("add_#{type}_paths".to_sym) do |additional_paths|
 124            ::ActiveSupport::Deprecation.warn("ExtensionLoader.add_#{type}_paths is has been moved and is deprecated. Please use Radiant.configuration.add_#{type}_paths", caller)
 125            initializer.configuration.send("add_#{type}_paths".to_sym, additional_paths)
 126          end
 127        end
 128      end
 129    end
 130  end