aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/plugin.rb
blob: c64042cf7d52ca3ee34a80eee7324ec3697a2986 (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
116
117
118
119
120
121
122
123
124
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 if blk
      @rake_tasks
    end

    def rake_tasks
      self.class.rake_tasks
    end

    def 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

      def load_tasks
        Dir["#{path}/**/tasks/**/*.rake"].sort.each { |ext| load ext }
      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