From 15c466dd729e744379380d08b8c25b9860fd836d Mon Sep 17 00:00:00 2001
From: Marcel Molina <marcel@vernix.org>
Date: Fri, 2 Mar 2007 23:39:29 +0000
Subject: Split out the basic plugin locator functionality into an abstract
 super class. Add a FileSystemLocator to do the job of checking the
 plugin_paths for plugins. Add plugin_locators configuration option which will
 iterate over the set of plugin locators and load each of the plugin loaders
 they return. Rename locater everywhere to locator. [Marcel Molina Jr.]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6290 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
---
 railties/lib/initializer.rb    | 23 ++++++++---
 railties/lib/plugin/loader.rb  | 38 +++++++++++++++---
 railties/lib/plugin/locater.rb | 88 ------------------------------------------
 railties/lib/plugin/locator.rb | 75 +++++++++++++++++++++++++++++++++++
 4 files changed, 126 insertions(+), 98 deletions(-)
 delete mode 100644 railties/lib/plugin/locater.rb
 create mode 100644 railties/lib/plugin/locator.rb

(limited to 'railties/lib')

diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index b2b7b3b545..36797026c4 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -2,7 +2,7 @@ require 'logger'
 require 'set'
 require File.join(File.dirname(__FILE__), 'railties_path')
 require File.join(File.dirname(__FILE__), 'rails/version')
-require File.join(File.dirname(__FILE__), 'plugin/locater')
+require File.join(File.dirname(__FILE__), 'plugin/locator')
 require File.join(File.dirname(__FILE__), 'plugin/loader')
 
 
@@ -183,12 +183,14 @@ module Rails
     # * evaluate <tt>init.rb</tt> if present
     #
     # After all plugins are loaded, duplicates are removed from the load path.
-    # If an array of plugin names is specified in config.plugins, the plugins
-    # will be loaded in that order. Otherwise, plugins are loaded in alphabetical
+    # If an array of plugin names is specified in config.plugins, only those plugins will be loaded
+    # and they plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical
     # order.
     def load_plugins
-      Plugin::Locater.new(self).each do |plugin|
-        plugin.load
+      configuration.plugin_locators.each do |locator|
+        locator.new(self).each do |plugin|
+          plugin.load
+        end
       end
       $LOAD_PATH.uniq!      
     end
@@ -429,6 +431,12 @@ module Rails
     # <tt>vendor/plugins</tt>.
     attr_accessor :plugin_paths
     
+    # The classes that handle finding the desired plugins that you'd like to load for
+    # your application. By default it is the Rails::Plugin::FileSystemLocator which finds
+    # plugins to load in <tt>vendor/plugins</tt>. You can hook into gem location by subclassing
+    # Rails::Plugin::Locator and adding it onto the list of <tt>plugin_locators</tt>.
+    attr_accessor :plugin_locators
+    
     # The class that handles loading each plugin. Defaults to Rails::Plugin::Loader, but 
     # a sub class would have access to fine grained modification of the loading behavior. See
     # the implementation of Rails::Plugin::Loader for more details.
@@ -449,6 +457,7 @@ module Rails
       self.whiny_nils                   = default_whiny_nils
       self.plugins                      = default_plugins
       self.plugin_paths                 = default_plugin_paths
+      self.plugin_locators              = default_plugin_locators
       self.plugin_loader                = default_plugin_loader
       self.database_configuration_file  = default_database_configuration_file
 
@@ -605,6 +614,10 @@ module Rails
         ["#{root_path}/vendor/plugins"]
       end
       
+      def default_plugin_locators
+        [Plugin::FileSystemLocator]
+      end
+      
       def default_plugin_loader
         Plugin::Loader
       end
diff --git a/railties/lib/plugin/loader.rb b/railties/lib/plugin/loader.rb
index c3116d84c5..d5ad3aa8e3 100644
--- a/railties/lib/plugin/loader.rb
+++ b/railties/lib/plugin/loader.rb
@@ -32,16 +32,36 @@ module Rails
       def plugin_path?
         File.directory?(directory) && (has_lib_directory? || has_init_file?)
       end
-    
+      
       def enabled?
-        config.plugins.nil? || config.plugins.include?(name)
+        !explicit_plugin_loading_order? || registered?
+      end
+        
+      def registered?
+        explicit_plugin_loading_order? && registered_plugins.include?(name)
+      end
+      
+      def plugin_does_not_exist!(plugin_name = name)
+        raise LoadError, "Can not find the plugin named: #{plugin_name}"
       end
       
       private
+        # The plugins that have been explicitly listed with config.plugins. If this list is nil
+        # then it means the client does not care which plugins or in what order they are loaded, 
+        # so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is
+        # non empty, we load the named plugins in the order specified.
+        def registered_plugins
+          config.plugins
+        end
+        
+        def explicit_plugin_loading_order?
+          !registered_plugins.nil?
+        end
+        
         def report_nonexistant_or_empty_plugin!
-          raise LoadError, "No such plugin: #{directory}" unless plugin_path?
+          plugin_does_not_exist! unless plugin_path?
         end
-  
+        
         def lib_path
           File.join(directory, 'lib')
         end
@@ -88,7 +108,15 @@ module Rails
         end
       
         def <=>(other_plugin_loader)
-          name <=> other_plugin_loader.name
+          if explicit_plugin_loading_order?
+            if non_existent_plugin = [self, other_plugin_loader].detect {|plugin| !registered_plugins.include?(plugin.name)}
+              plugin_does_not_exist!(non_existent_plugin.name)
+            end
+            
+            registered_plugins.index(name) <=> registered_plugins.index(other_plugin_loader.name)
+          else
+            name <=> other_plugin_loader.name
+          end
         end
     end
   end
diff --git a/railties/lib/plugin/locater.rb b/railties/lib/plugin/locater.rb
deleted file mode 100644
index 4a7aa774ee..0000000000
--- a/railties/lib/plugin/locater.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-module Rails
-  module Plugin
-    class Locater
-      include Enumerable
-      attr_reader :initializer
-      
-      def initialize(initializer)
-        @initializer = initializer
-      end
-      
-      def plugins
-        if !explicit_plugin_loading_order?
-          # We don't care about which plugins get loaded or in what order they are loaded
-          # so we load 'em all in a reliable order
-          located_plugins.sort
-        elsif !registered_plugins.empty?
-          registered_plugins.inject([]) do |plugins, registered_plugin|
-            report_plugin_missing!(registered_plugin) unless plugin = locate_registered_plugin(registered_plugin)
-            plugins << plugin
-          end
-        else
-          []
-        end
-      end
-      
-      def each(&block)
-        plugins.each(&block)
-      end
-      
-      def plugin_names
-        plugins.map {|plugin| plugin.name}
-      end
-      
-      private
-        def locate_registered_plugin(registered_plugin)
-          located_plugins.detect {|plugin| plugin.name == registered_plugin }
-        end
-        
-        def report_plugin_missing!(name)
-          raise LoadError, "Cannot find the plugin you registered called '#{name}'!"
-        end
-        
-        def explicit_plugin_loading_order?
-          !registered_plugins.nil?
-        end
-        
-        # The plugins that have been explicitly listed with config.plugins. If this list is nil
-        # then it means the client does not care which plugins or in what order they are loaded, 
-        # so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is
-        # non empty, we load the named plugins in the order specified.
-        def registered_plugins
-          initializer.configuration.plugins
-        end
-      
-        def located_plugins
-          # We cache this as locate_plugins_under on the entire set of plugin directories could 
-          # be potentially expensive
-          @located_plugins ||=
-            begin
-              initializer.configuration.plugin_paths.flatten.inject([]) do |plugins, path|
-                plugins.concat locate_plugins_under(path)
-                plugins
-              end.flatten
-            end         
-        end
-        
-        # This starts at the base path looking for directories that pass the plugin_path? test of the Plugin::Loader.
-        # Since plugins can be nested arbitrarily deep within an unspecified number of intermediary directories, 
-        # this method runs recursively until it finds a plugin directory.
-        #
-        #   e.g.
-        #
-        #     locate_plugins_under('vendor/plugins/acts/acts_as_chunky_bacon')
-        #     => 'acts_as_chunky_bacon' 
-        def locate_plugins_under(base_path)
-           Dir.glob(File.join(base_path, '*')).inject([]) do |plugins, path|
-            plugin_loader = initializer.configuration.plugin_loader.new(initializer, path)
-            if plugin_loader.plugin_path?
-              plugins << plugin_loader if plugin_loader.enabled?
-            elsif File.directory?(path)
-              plugins.concat locate_plugins_under(path)
-            end
-            plugins
-          end
-        end
-    end
-  end
-end
\ No newline at end of file
diff --git a/railties/lib/plugin/locator.rb b/railties/lib/plugin/locator.rb
new file mode 100644
index 0000000000..326a2a74f5
--- /dev/null
+++ b/railties/lib/plugin/locator.rb
@@ -0,0 +1,75 @@
+module Rails
+  module Plugin
+    class Locator
+      include Enumerable
+      attr_reader :initializer
+      
+      def initialize(initializer)
+        @initializer = initializer
+      end
+      
+      def plugins
+        located_plugins.select(&:enabled?).sort
+      end
+      
+      def each(&block)
+        plugins.each(&block)
+      end
+      
+      def plugin_names
+        plugins.map(&:name)
+      end
+      
+      private
+        def located_plugins
+          raise "The `located_plugins' method must be defined by concrete subclasses of #{self.class}"
+        end
+    end
+    
+    class FileSystemLocator < Locator
+        private
+          def located_plugins
+            returning locate_plugins do |loaders|
+              ensure_all_registered_plugins_are_loaded!(loaders)
+            end
+          end
+          
+          def locate_plugins
+            initializer.configuration.plugin_paths.flatten.inject([]) do |plugins, path|
+              plugins.concat locate_plugins_under(path)
+              plugins
+            end.flatten
+          end
+          
+          def ensure_all_registered_plugins_are_loaded!(loaders)
+            registered_plugins = initializer.configuration.plugins
+            unless registered_plugins.nil? || registered_plugins.empty?
+              missing_plugins = registered_plugins - loaders.map(&:name)
+              unless missing_plugins.empty?
+                raise LoadError, "Could not locate the following plugins: #{missing_plugins.inspect}"
+              end
+            end
+          end
+
+          # This starts at the base path looking for directories that pass the plugin_path? test of the Plugin::Loader.
+          # Since plugins can be nested arbitrarily deep within an unspecified number of intermediary directories, 
+          # this method runs recursively until it finds a plugin directory.
+          #
+          #   e.g.
+          #
+          #     locate_plugins_under('vendor/plugins/acts/acts_as_chunky_bacon')
+          #     => 'acts_as_chunky_bacon' 
+          def locate_plugins_under(base_path)
+             Dir.glob(File.join(base_path, '*')).inject([]) do |plugins, path|
+              plugin_loader = initializer.configuration.plugin_loader.new(initializer, path)
+              if plugin_loader.plugin_path? && plugin_loader.enabled?
+                plugins << plugin_loader
+              elsif File.directory?(path)
+                plugins.concat locate_plugins_under(path)
+              end
+              plugins
+            end
+          end
+    end
+  end
+end
\ No newline at end of file
-- 
cgit v1.2.3