aboutsummaryrefslogblamecommitdiffstats
path: root/railties/lib/rails/configuration.rb
blob: cb321536d2a885d568b7ffc84e196b1972ab9f72 (plain) (tree)
1
2
3
                                        
 
            

















                                                                



                                                                     

                      

       






                                         
                                                                          

                                                         





                                             



















                                                                    
                                                                            





                                                           









                                                                             
 
                              
           

                                        
                                          
                                          





                                            

                     
                                                          
                                                                                        
                                            
 


                                                                                               

           
                                                                          
 


                                            



                   
                                            




















                                                                                             









                                                                                



                                                  














                                                                                                               
                                                                                        

       







                                                                             
                                 
                                                                           

       



                                                                                             

                                 
                                                       


                                        

       

                            

                                               


                       


         
                                   
                                                                                

       
                 
                                                    

       

                               



                       
                                                                            

       




                                                               
                                                                                                               

                                            
                                                     










                                            
                                                                              


                                        






                                                                            
                
                                                              

       

                                                               

       

                                                                                                            

       

                     
                                                
                           
 

                                                                                   

                                 
 

            

       
                        
                                                   

       

                                     
                                


                                                           
           
     
                                                  

                                                  









                                    
                                                
     
                                                   
     

                                  

       
                             
                                                         
 
                    

                                               
                                

         
                                       
                                                 
 







                                                           




                                                        
           

         
     
   
require 'active_support/ordered_options'

module Rails
  # Create a Plugin::Options from ActiveSuppot::OrderedOptions,
  # which support the following syntax:
  #
  #   controller.action_controller.include FooBar
  #
  class Plugin::Options < ActiveSupport::OrderedOptions #:nodoc:
    attr_reader :includes

    def initialize(*args)
      @includes = []
      super
    end

    def include(*args)
      @includes.concat(args)
    end
  end

  # Temporarily separate the plugin configuration class from the main
  # configuration class while this bit is being cleaned up.
  class Plugin::Configuration

    def self.default
      @default ||= new
    end

    attr_reader :middleware

    def initialize(base = nil)
      if base
        @options    = base.options.dup
        @middleware = base.middleware.dup
      else
        @options    = Hash.new { |h,k| h[k] = Rails::Plugin::Options.new }
        @middleware = ActionDispatch::MiddlewareStack.new
      end
    end

    def respond_to?(name)
      super || name.to_s =~ config_key_regexp
    end

  protected

    attr_reader :options

  private

    def method_missing(name, *args, &blk)
      if name.to_s =~ config_key_regexp
        return $2 == '=' ? @options[$1] = args.first : @options[$1]
      end

      super
    end

    def config_key_regexp
      bits = config_keys.map { |n| Regexp.escape(n.to_s) }.join('|')
      /^(#{bits})(?:=)?$/
    end

    def config_keys
      ([ :active_support, :action_view, :action_mailer, :active_resource ] +
        Plugin.plugin_names).map { |n| n.to_s }.uniq
    end
  end

  class Configuration < Plugin::Configuration
    attr_accessor :after_initialize_blocks, :cache_classes,
                  :consider_all_requests_local, :dependency_loading, :gems,
                  :load_once_paths, :logger, :metals, :plugins,
                  :preload_frameworks, :reload_plugins, :serve_static_assets,
                  :time_zone, :whiny_nils

    attr_writer :cache_store, :controller_paths,
                :database_configuration_file, :eager_load_paths,
                :frameworks, :framework_root_path, :i18n, :load_paths,
                :log_level, :log_path, :paths, :routes_configuration_file,
                :view_path

    def initialize(base = nil)
      super
      @load_once_paths              = []
      @after_initialize_blocks      = []
      @dependency_loading           = true
      @serve_static_assets          = true
    end

    def after_initialize(&blk)
      @after_initialize_blocks << blk if blk
    end

    def root
      @root ||= begin
        call_stack = caller.map { |p| p.split(':').first }
        root_path  = call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] }
        root_path  = File.dirname(root_path)

        while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru")
          parent = File.dirname(root_path)
          root_path = parent != root_path && parent
        end

        root = File.exist?("#{root_path}/config.ru") ? root_path : Dir.pwd

        RUBY_PLATFORM =~ /(:?mswin|mingw)/ ?
          Pathname.new(root).expand_path :
          Pathname.new(root).realpath
      end
    end

    def root=(root)
      @root = Pathname.new(root).expand_path
    end

    def paths
      @paths ||= begin
        paths = Rails::Application::Root.new(root)
        paths.app                 "app",             :load_path => true
        paths.app.metals          "app/metal",       :eager_load => true
        paths.app.models          "app/models",      :eager_load => true
        paths.app.controllers     "app/controllers", builtin_directories, :eager_load => true
        paths.app.helpers         "app/helpers",     :eager_load => true
        paths.app.services        "app/services",    :load_path => true
        paths.lib                 "lib",             :load_path => true
        paths.vendor              "vendor",          :load_path => true
        paths.vendor.plugins      "vendor/plugins"
        paths.tmp                 "tmp"
        paths.tmp.cache           "tmp/cache"
        paths.config              "config"
        paths.config.locales      "config/locales"
        paths.config.environments "config/environments", :glob => "#{RAILS_ENV}.rb"
        paths
      end
    end

    # Enable threaded mode. Allows concurrent requests to controller actions and
    # multiple database connections. Also disables automatic dependency loading
    # after boot, and disables reloading code on every request, as these are
    # fundamentally incompatible with thread safety.
    def threadsafe!
      self.preload_frameworks = true
      self.cache_classes = true
      self.dependency_loading = false

      if respond_to?(:action_controller)
        action_controller.allow_concurrency = true
      end
      self
    end

    def framework_paths
      paths = %w(railties railties/lib activesupport/lib)
      paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view)

      [:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework|
        paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework)
      end

      paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
    end

    def framework_root_path
      defined?(::RAILS_FRAMEWORK_ROOT) ? ::RAILS_FRAMEWORK_ROOT : "#{root}/vendor/rails"
    end

    # Loads and returns the contents of the #database_configuration_file. The
    # contents of the file are processed via ERB before being sent through
    # YAML::load.
    def database_configuration
      require 'erb'
      YAML::load(ERB.new(IO.read(database_configuration_file)).result)
    end

    def routes_configuration_file
      @routes_configuration_file ||= File.join(root, 'config', 'routes.rb')
    end

    def builtin_routes_configuration_file
      @builtin_routes_configuration_file ||= File.join(RAILTIES_PATH, 'builtin', 'routes.rb')
    end

    def controller_paths
      @controller_paths ||= begin
        paths = [File.join(root, 'app', 'controllers')]
        paths.concat builtin_directories
        paths
      end
    end

    def cache_store
      @cache_store ||= begin
        if File.exist?("#{root}/tmp/cache/")
          [ :file_store, "#{root}/tmp/cache/" ]
        else
          :memory_store
        end
      end
    end

    def database_configuration_file
      @database_configuration_file ||= File.join(root, 'config', 'database.yml')
    end

    def view_path
      @view_path ||= File.join(root, 'app', 'views')
    end

    def eager_load_paths
      @eager_load_paths ||= %w(
        app/metal
        app/models
        app/controllers
        app/helpers
      ).map { |dir| "#{root}/#{dir}" }.select { |dir| File.directory?(dir) }
    end

    def load_paths
      @load_paths ||= begin
        paths = []

        # Add the old mock paths only if the directories exists
        paths.concat(Dir["#{root}/test/mocks/#{RAILS_ENV}"]) if File.exists?("#{root}/test/mocks/#{RAILS_ENV}")

        # Add the app's controller directory
        paths.concat(Dir["#{root}/app/controllers/"])

        # Followed by the standard includes.
        paths.concat %w(
          app
          app/metal
          app/models
          app/controllers
          app/helpers
          app/services
          lib
          vendor
        ).map { |dir| "#{root}/#{dir}" }.select { |dir| File.directory?(dir) }

        paths.concat builtin_directories
      end
    end

    def builtin_directories
      # Include builtins only in the development environment.
      (RAILS_ENV == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
    end

    def log_path
      @log_path ||= File.join(root, 'log', "#{RAILS_ENV}.log")
    end

    def log_level
      @log_level ||= RAILS_ENV == 'production' ? :info : :debug
    end

    def frameworks
      @frameworks ||= [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
    end

    def i18n
      @i18n ||= begin
        i18n = ActiveSupport::OrderedOptions.new
        i18n.load_path = []

        if File.exist?(File.join(root, 'config', 'locales'))
          i18n.load_path << Dir[File.join(root, 'config', 'locales', '*.{rb,yml}')]
          i18n.load_path.flatten!
        end

        i18n
      end
    end

    def environment_path
      "#{root}/config/environments/#{RAILS_ENV}.rb"
    end

    # Holds generators configuration:
    #
    #   config.generators do |g|
    #     g.orm             :datamapper, :migration => true
    #     g.template_engine :haml
    #     g.test_framework  :rspec
    #   end
    #
    # If you want to disable color in console, do:
    #
    #   config.generators.colorize_logging = false
    #
    def generators
      @generators ||= Generators.new
      if block_given?
        yield @generators
      else
        @generators
      end
    end

    # Allows Notifications queue to be modified.
    #
    #   config.notifications.queue = MyNewQueue.new
    #
    def notifications
      ActiveSupport::Notifications
    end

    class Generators #:nodoc:
      attr_accessor :aliases, :options, :colorize_logging

      def initialize
        @aliases = Hash.new { |h,k| h[k] = {} }
        @options = Hash.new { |h,k| h[k] = {} }
        @colorize_logging = true
      end

      def method_missing(method, *args)
        method = method.to_s.sub(/=$/, '').to_sym

        if method == :rails
          namespace, configuration = :rails, args.shift
        elsif args.first.is_a?(Hash)
          namespace, configuration = method, args.shift
        else
          namespace, configuration = args.shift, args.shift
          @options[:rails][method] = namespace
        end

        if configuration
          aliases = configuration.delete(:aliases)
          @aliases[namespace].merge!(aliases) if aliases
          @options[namespace].merge!(configuration)
        end
      end
    end
  end
end