aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/plugin/locater.rb
blob: 4a7aa774eef7c5e551fdaf785d7dfbf7c77c4a2f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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