aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/plugin.rb
blob: be6cdec3fabd1a406d79abb22aae4be40775c071 (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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
module Rails
  class Plugin
    include Initializable

    def self.plugin_name(plugin_name = nil)
      @plugin_name ||= name.demodulize.underscore
      @plugin_name = plugin_name if plugin_name
      @plugin_name
    end

    def self.inherited(klass)
      @plugins ||= []
      @plugins << klass unless klass == Vendored
    end

    def self.plugins
      @plugins
    end

    def self.plugin_names
      plugins.map { |p| p.plugin_name }
    end

    def self.config
      Configuration.default
    end

    def self.rake_tasks(&blk)
      @rake_tasks ||= []
      @rake_tasks << blk
    end

    def self.load_tasks
      return unless @rake_tasks
      @rake_tasks.each { |blk| blk.call }
    end

    # Creates an initializer which includes all given modules to the given class.
    #
    #   module Rails
    #     class ActionController < Rails::Plugin
    #       plugin_name :action_controller
    #       include_modules_in "ActionController::Base"
    #     end
    #   end
    #
    def self.include_modules_in(klass, from=plugin_name)
      self.initializer :"#{from}.include_modules" do |app|
        klass = klass.constantize if klass.is_a?(String)
        app.config.send(from).includes.each do |mod|
          klass.send(:include, mod.is_a?(String) ? mod.constantize : mod)
        end
      end
    end

    class Vendored < Plugin
      def self.all(list, paths)
        plugins = []
        paths.each do |path|
          Dir["#{path}/*"].each do |plugin_path|
            plugin = new(plugin_path)
            next unless list.include?(plugin.name) || list.include?(:all)
            plugins << plugin
          end
        end

        plugins.sort_by do |p|
          [list.index(p.name) || list.index(:all), p.name.to_s]
        end
      end

      attr_reader :name, :path

      def initialize(path)
        @name = File.basename(path).to_sym
        @path = path
      end

      def load_paths
        Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"]
      end

      initializer :add_to_load_path, :after => :set_autoload_paths do |app|
        load_paths.each do |path|
          $LOAD_PATH << path
          require "active_support/dependencies"

          ActiveSupport::Dependencies.load_paths << path

          unless app.config.reload_plugins
            ActiveSupport::Dependencies.load_once_paths << path
          end
        end
      end

      initializer :load_init_rb, :before => :load_application_initializers do |app|
        file   = "#{@path}/init.rb"
        config = app.config
        eval File.read(file), binding, file if File.file?(file)
      end

      initializer :add_view_paths, :after => :initialize_framework_views do
        ActionController::Base.view_paths.concat ["#{path}/app/views"] if File.directory?("#{path}/app/views")
      end

      initializer :add_routing_file, :after => :initialize_routing do |app|
        routing_file = "#{path}/config/routes.rb"
        if File.exist?(routing_file)
          app.route_configuration_files << routing_file
          app.reload_routes!
        end
      end
    end
  end
end