Skip to content

Commit

Permalink
Get rid of config.preload_frameworks in favor of config.eager_load_na…
Browse files Browse the repository at this point in the history
…mespaces

The new option allows any Ruby namespace to be registered and set
up for eager load. We are effectively exposing the structure existing
in Rails since v3.0 for all developers in order to make their applications
thread-safe and CoW friendly.
  • Loading branch information
josevalim committed Aug 21, 2012
1 parent a1687e4 commit 2801786
Show file tree
Hide file tree
Showing 23 changed files with 80 additions and 52 deletions.
5 changes: 4 additions & 1 deletion actionmailer/lib/action_mailer.rb
Expand Up @@ -35,7 +35,10 @@
module ActionMailer
extend ::ActiveSupport::Autoload

autoload :Collector
eager_autoload do
autoload :Collector
end

autoload :Base
autoload :DeliveryMethods
autoload :MailHelper
Expand Down
1 change: 1 addition & 0 deletions actionmailer/lib/action_mailer/railtie.rb
Expand Up @@ -5,6 +5,7 @@
module ActionMailer
class Railtie < Rails::Railtie
config.action_mailer = ActiveSupport::OrderedOptions.new
config.eager_load_namespaces << ActionMailer

initializer "action_mailer.logger" do
ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger }
Expand Down
6 changes: 6 additions & 0 deletions actionpack/lib/action_controller.rb
Expand Up @@ -48,6 +48,12 @@ module ActionController
eager_autoload do
autoload :RecordIdentifier
end

def self.eager_load!
super
ActionController::Caching.eager_load!
HTML.eager_load!
end
end

# All of these simply register additional autoloads
Expand Down
2 changes: 2 additions & 0 deletions actionpack/lib/action_controller/railtie.rb
Expand Up @@ -9,6 +9,8 @@ module ActionController
class Railtie < Rails::Railtie #:nodoc:
config.action_controller = ActiveSupport::OrderedOptions.new

config.eager_load_namespaces << ActionController

initializer "action_controller.assets_config", :group => :all do |app|
app.config.action_controller.assets_dir ||= app.config.paths["public"].first
end
Expand Down
8 changes: 5 additions & 3 deletions actionpack/lib/action_dispatch.rb
Expand Up @@ -38,9 +38,11 @@ module ActionDispatch
class IllegalStateError < StandardError
end

autoload_under 'http' do
autoload :Request
autoload :Response
eager_autoload do
autoload_under 'http' do
autoload :Request
autoload :Response
end
end

autoload_under 'middleware' do
Expand Down
2 changes: 2 additions & 0 deletions actionpack/lib/action_dispatch/railtie.rb
Expand Up @@ -25,6 +25,8 @@ class Railtie < Rails::Railtie
'X-Content-Type-Options' => 'nosniff'
}

config.eager_load_namespaces << ActionDispatch

initializer "action_dispatch.configure" do |app|
ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
Expand Down
6 changes: 5 additions & 1 deletion actionpack/lib/action_view.rb
Expand Up @@ -38,7 +38,6 @@ module ActionView
autoload :PathSet
autoload :Template


autoload_under "renderer" do
autoload :Renderer
autoload :AbstractRenderer
Expand Down Expand Up @@ -77,6 +76,11 @@ module ActionView
autoload :TestCase

ENCODING_FLAG = '#.*coding[:=]\s*(\S+)[ \t]*'

def self.eager_load!
super
ActionView::Template.eager_load!
end
end

require 'active_support/core_ext/string/output_safety'
Expand Down
2 changes: 2 additions & 0 deletions actionpack/lib/action_view/railtie.rb
Expand Up @@ -9,6 +9,8 @@ class Railtie < Rails::Railtie
config.action_view.javascript_expansions = { :defaults => %w(jquery jquery_ujs) }
config.action_view.embed_authenticity_token_in_remote_forms = false

config.eager_load_namespaces << ActionView

initializer "action_view.embed_authenticity_token_in_remote_forms" do |app|
ActiveSupport.on_load(:action_view) do
ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms =
Expand Down
16 changes: 13 additions & 3 deletions activemodel/lib/active_model.rb
Expand Up @@ -34,7 +34,6 @@ module ActiveModel
autoload :Conversion
autoload :Dirty
autoload :EachValidator, 'active_model/validator'
autoload :Errors
autoload :Lint
autoload :MassAssignmentSecurity
autoload :Model
Expand All @@ -49,11 +48,22 @@ module ActiveModel
autoload :Validations
autoload :Validator

eager_autoload do
autoload :Errors
end

module Serializers
extend ActiveSupport::Autoload

autoload :JSON
autoload :Xml
eager_autoload do
autoload :JSON
autoload :Xml
end
end

def eager_load!
super
ActiveModel::Serializer.eager_load!
end
end

Expand Down
8 changes: 7 additions & 1 deletion activemodel/lib/active_model/railtie.rb
@@ -1,2 +1,8 @@
require "active_model"
require "rails"
require "rails"

module ActiveModel
class Railtie < Rails::Railtie
config.eager_load_namespaces << ActiveModel
end
end
9 changes: 9 additions & 0 deletions activerecord/lib/active_record.rb
Expand Up @@ -160,6 +160,15 @@ module Tasks

autoload :TestCase
autoload :TestFixtures, 'active_record/fixtures'

def self.eager_load!
super
ActiveRecord::Locking.eager_load!
ActiveRecord::Scoping.eager_load!
ActiveRecord::Associations.eager_load!
ActiveRecord::AttributeMethods.eager_load!
ActiveRecord::ConnectionAdapters.eager_load!
end
end

ActiveSupport.on_load(:active_record) do
Expand Down
3 changes: 3 additions & 0 deletions activerecord/lib/active_record/railtie.rb
Expand Up @@ -29,8 +29,11 @@ class Railtie < Rails::Railtie
'ActiveRecord::RecordNotSaved' => :unprocessable_entity
)


config.active_record.use_schema_cache_dump = true

config.eager_load_namespaces << ActiveRecord

rake_tasks do
require "active_record/base"
load "active_record/railties/databases.rake"
Expand Down
2 changes: 2 additions & 0 deletions activesupport/lib/active_support/railtie.rb
Expand Up @@ -5,6 +5,8 @@ module ActiveSupport
class Railtie < Rails::Railtie
config.active_support = ActiveSupport::OrderedOptions.new

config.eager_load_namespaces << ActiveSupport

initializer "active_support.deprecation_behavior" do |app|
if deprecation = app.config.active_support.deprecation
ActiveSupport::Deprecation.behavior = deprecation
Expand Down
6 changes: 1 addition & 5 deletions guides/source/configuring.textile
Expand Up @@ -107,8 +107,6 @@ end

* +config.middleware+ allows you to configure the application's middleware. This is covered in depth in the "Configuring Middleware":#configuring-middleware section below.

* +config.preload_frameworks+ enables or disables preloading all frameworks at startup. Enabled by +config.threadsafe!+. Defaults to +nil+, so is disabled.

* +config.queue+ configures a different queue implementation for the application. Defaults to +Rails::Queueing::Queue+. Note that, if the default queue is changed, the default +queue_consumer+ is not going to be initialized, it is up to the new queue implementation to handle starting and shutting down its own consumer(s).

* +config.queue_consumer+ configures a different consumer implementation for the default queue. Defaults to +Rails::Queueing::ThreadedConsumer+.
Expand All @@ -127,7 +125,7 @@ config.session_store :my_custom_store

This custom store must be defined as +ActionDispatch::Session::MyCustomStore+. In addition to symbols, they can also be objects implementing a certain API, like +ActiveRecord::SessionStore+, in which case no special namespace is required.

* +config.threadsafe!+ enables +cache_classes+, +dependency_loading+, +eager_load+ and +preload_frameworks+ to make the application threadsafe.
* +config.threadsafe!+ enables +cache_classes+ and +eager_load+ to make the application threadsafe.

WARNING: Threadsafe operation is incompatible with the normal workings of development mode Rails. In particular, automatic dependency loading and class reloading are automatically disabled when you call +config.threadsafe!+.

Expand Down Expand Up @@ -654,8 +652,6 @@ Serves as a placeholder so that +:load_environment_config+ can be defined to run

*+load_active_support+* Requires +active_support/dependencies+ which sets up the basis for Active Support. Optionally requires +active_support/all+ if +config.active_support.bare+ is un-truthful, which is the default.

*+preload_frameworks+* Loads all autoload dependencies of Rails automatically if +config.preload_frameworks+ is +true+ or "truthful". By default this configuration option is disabled. In Rails, when internal classes are referenced for the first time they are autoloaded. +:preload_frameworks+ loads all of this at once on initialization.

*+initialize_logger+* Initializes the logger (an +ActiveSupport::BufferedLogger+ object) for the application and makes it accessible at +Rails.logger+, provided that no initializer inserted before this point has defined +Rails.logger+.

*+initialize_cache+* If +Rails.cache+ isn't set yet, initializes the cache by referencing the value in +config.cache_store+ and stores the outcome as +Rails.cache+. If this object responds to the +middleware+ method, its middleware is inserted before +Rack::Runtime+ in the middleware stack.
Expand Down
7 changes: 0 additions & 7 deletions railties/lib/rails/application.rb
Expand Up @@ -83,13 +83,6 @@ def initialize
@queue = nil
end

# Eager load all dependencies before eager loading
# the application.
def eager_load!
railties.each(&:eager_load!)
super
end

# Returns true if the application is initialized.
def initialized?
@initialized
Expand Down
9 changes: 1 addition & 8 deletions railties/lib/rails/application/bootstrap.rb
Expand Up @@ -16,7 +16,7 @@ module Bootstrap
initializer :set_eager_load, :group => :all do
if config.eager_load.nil?
warn <<-INFO
config.eager_load is set to nil. Please update your config/environments file accordingly:
config.eager_load is set to nil. Please update your config/environments/*.rb files accordingly:
* development - set it to false
* test - set it to false (unless you use a tool that preloads your test environment)
Expand All @@ -27,13 +27,6 @@ module Bootstrap
end
end

# Preload all frameworks specified by the Configuration#frameworks.
# Used by Passenger to ensure everything's loaded before forking and
# to avoid autoload race conditions in JRuby.
initializer :preload_frameworks, :group => :all do
ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks
end

# Initialize the logger early in the stack in case we need to log some deprecation.
initializer :initialize_logger, :group => :all do
Rails.logger ||= config.logger || begin
Expand Down
3 changes: 1 addition & 2 deletions railties/lib/rails/application/configuration.rb
Expand Up @@ -9,7 +9,7 @@ class Configuration < ::Rails::Engine::Configuration
:cache_classes, :cache_store, :consider_all_requests_local, :console,
:eager_load, :exceptions_app, :file_watcher, :filter_parameters,
:force_ssl, :helpers_paths, :logger, :log_formatter, :log_tags,
:preload_frameworks, :railties_order, :relative_url_root, :secret_token,
:railties_order, :relative_url_root, :secret_token,
:serve_static_assets, :ssl_options, :static_cache_control, :session_options,
:time_zone, :reload_classes_only_on_change,
:queue, :queue_consumer
Expand Down Expand Up @@ -95,7 +95,6 @@ def paths
# after boot, and disables reloading code on every request, as these are
# fundamentally incompatible with thread safety.
def threadsafe!
@preload_frameworks = true
@cache_classes = true
@eager_load = true
self
Expand Down
2 changes: 1 addition & 1 deletion railties/lib/rails/application/finisher.rb
Expand Up @@ -52,7 +52,7 @@ module Finisher
initializer :eager_load! do
if config.eager_load
ActiveSupport.run_load_hooks(:before_eager_load, self)
eager_load!
config.eager_load_namespaces.each(&:eager_load!)
end
end

Expand Down
5 changes: 5 additions & 0 deletions railties/lib/rails/engine.rb
Expand Up @@ -339,11 +339,16 @@ class Engine < Railtie

class << self
attr_accessor :called_from, :isolated

alias :isolated? :isolated
alias :engine_name :railtie_name

delegate :eager_load!, to: :instance

def inherited(base)
unless base.abstract_railtie?
Rails::Railtie::Configuration.eager_load_namespaces << base

base.called_from = begin
# Remove the line number from backtraces making sure we don't leave anything behind
call_stack = caller.map { |p| p.sub(/:\d+.*/, '') }
Expand Down
3 changes: 0 additions & 3 deletions railties/lib/rails/railtie.rb
Expand Up @@ -178,9 +178,6 @@ def config
@config ||= Railtie::Configuration.new
end

def eager_load!
end

def railtie_namespace
@railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:railtie_namespace) }
end
Expand Down
10 changes: 10 additions & 0 deletions railties/lib/rails/railtie/configuration.rb
Expand Up @@ -7,6 +7,16 @@ 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 ||= []
Expand Down
16 changes: 0 additions & 16 deletions railties/test/application/configuration_test.rb
Expand Up @@ -176,22 +176,6 @@ def teardown
end
end

test "frameworks are not preloaded by default" do
require "#{app_path}/config/environment"

assert ActionController.autoload?(:Caching)
end

test "frameworks are preloaded with config.preload_frameworks is set" do
add_to_config <<-RUBY
config.preload_frameworks = true
RUBY

require "#{app_path}/config/environment"

assert !ActionView.autoload?(:AssetPaths)
end

test "filter_parameters should be able to set via config.filter_parameters" do
add_to_config <<-RUBY
config.filter_parameters += [ :foo, 'bar', lambda { |key, value|
Expand Down
1 change: 0 additions & 1 deletion railties/test/application/rake_test.rb
Expand Up @@ -75,7 +75,6 @@ def world
RUBY

output = Dir.chdir(app_path){ `rake do_nothing` }
puts output
assert_match "Hello world", output
end

Expand Down

0 comments on commit 2801786

Please sign in to comment.