aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails/railtie/configuration.rb
blob: 406ed5ac6175744dcb98fe8350bd45f477f5fbb6 (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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
require 'rails/configuration'

module Rails
  class Railtie
    class Configuration
      def initialize
        @@options ||= {}
      end

      # Expose the eager_load_namespaces at "module" level for convenience.
      def self.eager_load_namespaces #:nodoc:
        @@eager_load_namespaces ||= []
      end

      # All namespaces that are eager loaded
      def eager_load_namespaces
        @@eager_load_namespaces ||= []
      end

      # Add files that should be watched for change.
      def watchable_files
        @@watchable_files ||= []
      end

      # Add directories that should be watched for change.
      # The key of the hashes should be directories and the values should
      # be an array of extensions to match in each directory.
      def watchable_dirs
        @@watchable_dirs ||= {}
      end

      # This allows you to modify the application's middlewares from Engines.
      #
      # All operations you run on the app_middleware will be replayed on the
      # application once it is defined and the default_middlewares are
      # created
      def app_middleware
        @@app_middleware ||= Rails::Configuration::MiddlewareStackProxy.new
      end

      # This allows you to modify application's generators from Railties.
      #
      # Values set on app_generators will become defaults for application, unless
      # application overwrites them.
      def app_generators
        @@app_generators ||= Rails::Configuration::Generators.new
        yield(@@app_generators) if block_given?
        @@app_generators
      end

      # First configurable block to run. Called before any initializers are run.
      def before_configuration(&block)
        ActiveSupport.on_load(:before_configuration, yield: true, &block)
      end

      # Third configurable block to run. Does not run if +config.cache_classes+
      # set to false.
      def before_eager_load(&block)
        ActiveSupport.on_load(:before_eager_load, yield: true, &block)
      end

      # Second configurable block to run. Called before frameworks initialize.
      def before_initialize(&block)
        ActiveSupport.on_load(:before_initialize, yield: true, &block)
      end

      # Last configurable block to run. Called after frameworks initialize.
      def after_initialize(&block)
        ActiveSupport.on_load(:after_initialize, yield: true, &block)
      end

      # Array of callbacks defined by #to_prepare.
      def to_prepare_blocks
        @@to_prepare_blocks ||= []
      end

      # Defines generic callbacks to run before #after_initialize. Useful for
      # Rails::Railtie subclasses.
      def to_prepare(&blk)
        to_prepare_blocks << blk if blk
      end

      def respond_to?(name, include_private = false)
        super || @@options.key?(name.to_sym)
      end

    private

      def method_missing(name, *args, &blk)
        if name.to_s =~ /=$/
          key = $`.to_sym
          value = args.first

          if value.is_a?(Hash)
            @@options[key] = ChainedConfigurationOptions.new value
          else
            @@options[key] = value
          end
        elsif @@options.key?(name)
          @@options[name]
        else
          @@options[name] = ActiveSupport::OrderedOptions.new
        end
      end

      class ChainedConfigurationOptions < ActiveSupport::OrderedOptions # :nodoc:
        def initialize(value = nil)
          if value.is_a?(Hash)
            value.each_pair { |k, v| set_value k, v }
          else
            super
          end
        end

        def method_missing(meth, *args)
          if meth =~ /=$/
            key = $`.to_sym
            value = args.first

            set_value key, value
          else
            self.fetch(meth) { super }
          end
        end

        private

        def set_value(key, value)
          if value.is_a?(Hash)
            value = self.class.new(value)
          end

          self[key] = value
        end
      end
    end
  end
end