Skip to content
Browse files

Merge pull request #7225 from rails/eager_load

Improve eager load on Rails
  • Loading branch information...
2 parents 11e890f + da3d28e commit 6bef1469d2e43d0815b70588370470983a4320af @josevalim josevalim committed Aug 21, 2012
Showing with 215 additions and 109 deletions.
  1. +4 −1 actionmailer/lib/action_mailer.rb
  2. +1 −0 actionmailer/lib/action_mailer/railtie.rb
  3. +6 −0 actionpack/lib/action_controller.rb
  4. +2 −0 actionpack/lib/action_controller/railtie.rb
  5. +5 −3 actionpack/lib/action_dispatch.rb
  6. +2 −0 actionpack/lib/action_dispatch/railtie.rb
  7. +5 −1 actionpack/lib/action_view.rb
  8. +2 −0 actionpack/lib/action_view/railtie.rb
  9. +13 −3 activemodel/lib/active_model.rb
  10. +7 −1 activemodel/lib/active_model/railtie.rb
  11. +9 −0 activerecord/lib/active_record.rb
  12. +3 −0 activerecord/lib/active_record/railtie.rb
  13. +1 −2 activesupport/lib/active_support.rb
  14. +43 −17 activesupport/lib/active_support/dependencies/autoload.rb
  15. +2 −0 activesupport/lib/active_support/railtie.rb
  16. +1 −11 activesupport/test/{autoload.rb → autoload_test.rb}
  17. +7 −13 guides/source/configuring.textile
  18. +2 −0 railties/CHANGELOG.md
  19. +4 −3 railties/lib/rails/application.rb
  20. +12 −6 railties/lib/rails/application/bootstrap.rb
  21. +8 −12 railties/lib/rails/application/configuration.rb
  22. +3 −3 railties/lib/rails/application/finisher.rb
  23. +9 −0 railties/lib/rails/commands/server.rb
  24. +5 −0 railties/lib/rails/engine.rb
  25. +3 −0 railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
  26. +6 −0 railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
  27. +5 −0 railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
  28. +0 −3 railties/lib/rails/railtie.rb
  29. +10 −0 railties/lib/rails/railtie/configuration.rb
  30. +9 −27 railties/test/application/configuration_test.rb
  31. +2 −2 railties/test/application/middleware_test.rb
  32. +23 −0 railties/test/application/rake_test.rb
  33. +1 −1 railties/test/isolation/abstract_unit.rb
View
5 actionmailer/lib/action_mailer.rb
@@ -35,7 +35,10 @@
module ActionMailer
extend ::ActiveSupport::Autoload
- autoload :Collector
+ eager_autoload do
+ autoload :Collector
+ end
+
autoload :Base
autoload :DeliveryMethods
autoload :MailHelper
View
1 actionmailer/lib/action_mailer/railtie.rb
@@ -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 }
View
6 actionpack/lib/action_controller.rb
@@ -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
View
2 actionpack/lib/action_controller/railtie.rb
@@ -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
View
8 actionpack/lib/action_dispatch.rb
@@ -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
View
2 actionpack/lib/action_dispatch/railtie.rb
@@ -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
View
6 actionpack/lib/action_view.rb
@@ -38,7 +38,6 @@ module ActionView
autoload :PathSet
autoload :Template
-
autoload_under "renderer" do
autoload :Renderer
autoload :AbstractRenderer
@@ -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'
View
2 actionpack/lib/action_view/railtie.rb
@@ -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 =
View
16 activemodel/lib/active_model.rb
@@ -34,7 +34,6 @@ module ActiveModel
autoload :Conversion
autoload :Dirty
autoload :EachValidator, 'active_model/validator'
- autoload :Errors
autoload :Lint
autoload :MassAssignmentSecurity
autoload :Model
@@ -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
View
8 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
View
9 activerecord/lib/active_record.rb
@@ -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
View
3 activerecord/lib/active_record/railtie.rb
@@ -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"
View
3 activesupport/lib/active_support.rb
@@ -37,7 +37,6 @@ module ActiveSupport
autoload :LogSubscriber
autoload :Notifications
- # TODO: Narrow this list down
eager_autoload do
autoload :BacktraceCleaner
autoload :BasicObject
@@ -55,12 +54,12 @@ module ActiveSupport
autoload :OptionMerger
autoload :OrderedHash
autoload :OrderedOptions
- autoload :Rescuable
autoload :StringInquirer
autoload :TaggedLogging
autoload :XmlMini
end
+ autoload :Rescuable
autoload :SafeBuffer, "active_support/core_ext/string/output_safety"
autoload :TestCase
end
View
60 activesupport/lib/active_support/dependencies/autoload.rb
@@ -1,52 +1,78 @@
require "active_support/inflector/methods"
module ActiveSupport
+ # Autoload and eager load conveniences for your library.
+ #
+ # This module allows you to define autoloads based on
+ # Rails conventions (i.e. no need to define the path
+ # it is automatically guessed based on the filename)
+ # and also define a set of constants that needs to be
+ # eager loaded:
+ #
+ # module MyLib
+ # extend ActiveSupport::Autoload
+ #
+ # autoload :Model
+ #
+ # eager_autoload do
+ # autoload :Cache
+ # end
+ # end
+ #
+ # Then your library can be eager loaded by simply calling:
+ #
+ # MyLib.eager_load!
+ #
module Autoload
- @@autoloads = {}
- @@under_path = nil
- @@at_path = nil
- @@eager_autoload = false
+ def self.extended(base)
+ base.class_eval do
+ @_autoloads = {}
+ @_under_path = nil
+ @_at_path = nil
+ @_eager_autoload = false
+ end
+ end
- def autoload(const_name, path = @@at_path)
+ def autoload(const_name, path = @_at_path)
unless path
- full = [name, @@under_path, const_name.to_s, path].compact.join("::")
+ full = [name, @_under_path, const_name.to_s, path].compact.join("::")
path = Inflector.underscore(full)
end
- if @@eager_autoload
- @@autoloads[const_name] = path
+ if @_eager_autoload
+ @_autoloads[const_name] = path
end
super const_name, path
end
def autoload_under(path)
- @@under_path, old_path = path, @@under_path
+ @_under_path, old_path = path, @_under_path
yield
ensure
- @@under_path = old_path
+ @_under_path = old_path
end
def autoload_at(path)
- @@at_path, old_path = path, @@at_path
+ @_at_path, old_path = path, @_at_path
yield
ensure
- @@at_path = old_path
+ @_at_path = old_path
end
def eager_autoload
- old_eager, @@eager_autoload = @@eager_autoload, true
+ old_eager, @_eager_autoload = @_eager_autoload, true
yield
ensure
- @@eager_autoload = old_eager
+ @_eager_autoload = old_eager
end
- def self.eager_autoload!
- @@autoloads.values.each { |file| require file }
+ def eager_load!
+ @_autoloads.values.each { |file| require file }
end
def autoloads
- @@autoloads
+ @_autoloads
end
end
end
View
2 activesupport/lib/active_support/railtie.rb
@@ -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
View
12 activesupport/test/autoload.rb → activesupport/test/autoload_test.rb
@@ -28,15 +28,6 @@ module ::Fixtures::Autoload
assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
end
- test ":eager constants can be triggered via ActiveSupport::Autoload.eager_autoload!" do
- module ::Fixtures::Autoload
- autoload :SomeClass, "fixtures/autoload/some_class"
- end
- ActiveSupport::Autoload.eager_autoload!
- assert $LOADED_FEATURES.include?("fixtures/autoload/some_class.rb")
- assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
- end
-
test "the location of autoloaded constants defaults to :name.underscore" do
module ::Fixtures::Autoload
autoload :SomeClass
@@ -51,8 +42,7 @@ module ::Fixtures::Autoload
autoload :SomeClass
end
- ActiveSupport::Autoload.eager_autoload!
- assert $LOADED_FEATURES.include?("fixtures/autoload/some_class.rb")
+ ::Fixtures::Autoload.eager_load!
assert_nothing_raised { ::Fixtures::Autoload::SomeClass }
end
View
20 guides/source/configuring.textile
@@ -50,8 +50,6 @@ config.after_initialize do
end
</ruby>
-* +config.allow_concurrency+ should be true to allow concurrent (threadsafe) action processing. False by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Can also be enabled with +threadsafe!+.
-
* +config.asset_host+ sets the host for the assets. Useful when CDNs are used for hosting assets, or when you want to work around the concurrency constraints builtin in browsers using different domain aliases. Shorter version of +config.action_controller.asset_host+.
* +config.asset_path+ lets you decorate asset paths. This can be a callable, a string, or be +nil+ which is the default. For example, the normal path for +blog.js+ would be +/javascripts/blog.js+, let that absolute path be +path+. If +config.asset_path+ is a callable, Rails calls it when generating asset paths passing +path+ as argument. If +config.asset_path+ is a string, it is expected to be a +sprintf+ format string with a +%s+ where +path+ will get inserted. In either case, Rails outputs the decorated path. Shorter version of +config.action_controller.asset_path+.
@@ -89,6 +87,10 @@ end
* +config.dependency_loading+ is a flag that allows you to disable constant autoloading setting it to false. It only has effect if +config.cache_classes+ is true, which it is by default in production mode. This flag is set to false by +config.threadsafe!+.
+* +config.eager_load+ when true, eager loads all registered `config.eager_load_namespaces`. This includes your application, engines, Rails frameworks and any other registered namespace.
+
+* +config.eager_load_namespaces+ registers namespaces that are eager loaded when +config.eager_load+ is true. All namespaces in the list must respond to the +eager_load!+ method.
+
* +config.eager_load_paths+ accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. Defaults to every folder in the +app+ directory of the application.
* +config.encoding+ sets up the application-wide encoding. Defaults to UTF-8.
@@ -109,8 +111,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+.
@@ -129,10 +129,6 @@ 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 +allow_concurrency+, +cache_classes+, +dependency_loading+ and +preload_frameworks+ 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!+.
-
* +config.time_zone+ sets the default time zone for the application and enables time zone awareness for Active Record.
* +config.whiny_nils+ enables or disables warnings when a certain set of methods are invoked on +nil+ and it does not respond to them. Defaults to true in development and test environments.
@@ -203,7 +199,7 @@ Every Rails application comes with a standard set of middleware which it uses in
* +ActionDispatch::SSL+ forces every request to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to +true+. Options passed to this can be configured by using +config.ssl_options+.
* +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is +true+.
-* +Rack::Lock+ wraps the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to +false+, which it is by default.
+* +Rack::Lock+ wraps the app in mutex so it can only be called by a single thread at a time. Only enabled when +config.cache_classes_+ is +false+.
* +ActiveSupport::Cache::Strategy::LocalCache+ serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
* +Rack::Runtime+ sets an +X-Runtime+ header, containing the time (in seconds) taken to execute the request.
* +Rails::Rack::Logger+ notifies the logs that the request has began. After request is complete, flushes all the logs.
@@ -656,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.
@@ -752,13 +746,13 @@ The error occurred while evaluating nil.each
*+build_middleware_stack+* Builds the middleware stack for the application, returning an object which has a +call+ method which takes a Rack environment object for the request.
-*+eager_load!+* If +config.cache_classes+ is true, runs the +config.before_eager_load+ hooks and then calls +eager_load!+ which will load all the Ruby files from +config.eager_load_paths+.
+*+eager_load!+* If +config.eager_load+ is true, runs the +config.before_eager_load+ hooks and then calls +eager_load!+ which will load all +config.eager_load_namespaces+.
*+finisher_hook+* Provides a hook for after the initialization of process of the application is complete, as well as running all the +config.after_initialize+ blocks for the application, railties and engines.
*+set_routes_reloader+* Configures Action Dispatch to reload the routes file using +ActionDispatch::Callbacks.to_prepare+.
-*+disable_dependency_loading+* Disables the automatic dependency loading if the +config.cache_classes+ is set to true and +config.dependency_loading+ is set to false.
+*+disable_dependency_loading+* Disables the automatic dependency loading if the +config.eager_load+ is set to true.
h3. Database pooling
View
2 railties/CHANGELOG.md
@@ -5,6 +5,8 @@
default_url_options[:script_name] to set proper application's mount point by
yourself. *Piotr Sarnacki*
+* `config.threadsafe!` is deprecated in favor of `config.eager_load` which provides a more fine grained control on what is eager loaded *José Valim*
+
* The migration generator will now produce AddXXXToYYY/RemoveXXXFromYYY migrations with references statements, for instance
rails g migration AddReferencesToProducts user:references supplier:references{polymorphic}
View
7 railties/lib/rails/application.rb
@@ -16,7 +16,7 @@ module Rails
#
# Besides providing the same configuration as Rails::Engine and Rails::Railtie,
# the application object has several specific configurations, for example
- # "allow_concurrency", "cache_classes", "consider_all_requests_local", "filter_parameters",
+ # "cache_classes", "consider_all_requests_local", "filter_parameters",
# "logger" and so forth.
#
# Check Rails::Application::Configuration to see them all.
@@ -216,8 +216,9 @@ def run_tasks_blocks(app) #:nodoc:
railties.each { |r| r.run_tasks_blocks(app) }
super
require "rails/tasks"
+ config = self.config
task :environment do
- $rails_rake_task = true
+ config.eager_load = false
require_environment!
end
end
@@ -296,7 +297,7 @@ def default_middleware_stack #:nodoc:
middleware.use ::ActionDispatch::Static, paths["public"].first, config.static_cache_control
end
- middleware.use ::Rack::Lock unless config.allow_concurrency
+ middleware.use ::Rack::Lock unless config.cache_classes
middleware.use ::Rack::Runtime
middleware.use ::Rack::MethodOverride
middleware.use ::ActionDispatch::RequestId
View
18 railties/lib/rails/application/bootstrap.rb
@@ -13,11 +13,18 @@ module Bootstrap
require "active_support/all" unless config.active_support.bare
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
+ 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/*.rb files accordingly:
+
+ * development - set it to false
+ * test - set it to false (unless you use a tool that preloads your test environment)
+ * production - set it to true
+
+INFO
+ config.eager_load = config.cache_classes
+ end
end
# Initialize the logger early in the stack in case we need to log some deprecation.
@@ -60,7 +67,6 @@ module Bootstrap
end
# Sets the dependency loading mechanism.
- # TODO: Remove files from the $" and always use require.
initializer :initialize_dependency_mechanism, :group => :all do
ActiveSupport::Dependencies.mechanism = config.cache_classes ? :require : :load
end
View
20 railties/lib/rails/application/configuration.rb
@@ -5,11 +5,11 @@
module Rails
class Application
class Configuration < ::Rails::Engine::Configuration
- attr_accessor :allow_concurrency, :asset_host, :asset_path, :assets, :autoflush_log,
+ attr_accessor :asset_host, :asset_path, :assets, :autoflush_log,
:cache_classes, :cache_store, :consider_all_requests_local, :console,
- :dependency_loading, :exceptions_app, :file_watcher, :filter_parameters,
+ :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
@@ -20,11 +20,9 @@ class Configuration < ::Rails::Engine::Configuration
def initialize(*)
super
self.encoding = "utf-8"
- @allow_concurrency = false
@consider_all_requests_local = false
@filter_parameters = []
@helpers_paths = []
- @dependency_loading = true
@serve_static_assets = true
@static_cache_control = nil
@force_ssl = false
@@ -45,6 +43,7 @@ def initialize(*)
@log_formatter = ActiveSupport::Logger::SimpleFormatter.new
@queue = Rails::Queueing::Queue
@queue_consumer = Rails::Queueing::ThreadedConsumer
+ @eager_load = nil
@assets = ActiveSupport::OrderedOptions.new
@assets.enabled = false
@@ -91,15 +90,12 @@ def 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!
- @preload_frameworks = true
+ ActiveSupport::Deprecation.warn "config.threadsafe! is deprecated. Rails applications " \
+ "behave by default as thread safe in production as long as config.cache_classes and " \
+ "config.eager_load are set to true"
@cache_classes = true
- @dependency_loading = false
- @allow_concurrency = true
+ @eager_load = true
self
end
View
6 railties/lib/rails/application/finisher.rb
@@ -50,9 +50,9 @@ module Finisher
end
initializer :eager_load! do
- if config.cache_classes && !(defined?($rails_rake_task) && $rails_rake_task)
+ if config.eager_load
ActiveSupport.run_load_hooks(:before_eager_load, self)
- eager_load!
+ config.eager_load_namespaces.each(&:eager_load!)
end
end
@@ -91,7 +91,7 @@ module Finisher
# Disable dependency loading during request cycle
initializer :disable_dependency_loading do
- if config.cache_classes && !config.dependency_loading
+ if config.eager_load
ActiveSupport::Dependencies.unhook!
end
end
View
9 railties/lib/rails/commands/server.rb
@@ -87,6 +87,15 @@ def middleware
middlewares = []
middlewares << [Rails::Rack::Debugger] if options[:debugger]
middlewares << [::Rack::ContentLength]
+
+ # FIXME: add Rack::Lock in the case people are using webrick.
+ # This is to remain backwards compatible for those who are
+ # running webrick in production. We should consider removing this
+ # in development.
+ if server.name == 'Rack::Handler::WEBrick'
+ middlewares << [::Rack::Lock]
+ end
+
Hash.new(middlewares)
end
View
5 railties/lib/rails/engine.rb
@@ -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+.*/, '') }
View
3 railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -6,6 +6,9 @@
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
+ # Do not eager load code on boot.
+ config.eager_load = false
+
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
View
6 railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -4,6 +4,12 @@
# Code is not reloaded between requests.
config.cache_classes = true
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both thread web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
View
5 railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
@@ -7,6 +7,11 @@
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
# Configure static asset server for tests with Cache-Control for performance.
config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600"
View
3 railties/lib/rails/railtie.rb
@@ -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
View
10 railties/lib/rails/railtie/configuration.rb
@@ -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 ||= []
View
36 railties/test/application/configuration_test.rb
@@ -139,33 +139,31 @@ def teardown
assert_instance_of Pathname, Rails.root
end
- test "marking the application as threadsafe sets the correct config variables" do
+ test "initialize an eager loaded, cache classes app" do
add_to_config <<-RUBY
- config.threadsafe!
+ config.eager_load = true
+ config.cache_classes = true
RUBY
require "#{app_path}/config/application"
- assert AppTemplate::Application.config.allow_concurrency
+ assert AppTemplate::Application.initialize!
end
- test "initialize a threadsafe app" do
- add_to_config <<-RUBY
- config.threadsafe!
- RUBY
-
+ test "application is always added to eager_load namespaces" do
require "#{app_path}/config/application"
- assert AppTemplate::Application.initialize!
+ assert AppTemplate::Application, AppTemplate::Application.config.eager_load_namespaces
end
test "asset_path defaults to nil for application" do
require "#{app_path}/config/environment"
assert_equal nil, AppTemplate::Application.config.asset_path
end
- test "the application can be marked as threadsafe when there are no frameworks" do
+ test "the application can be eager loaded even when there are no frameworks" do
FileUtils.rm_rf("#{app_path}/config/environments")
add_to_config <<-RUBY
- config.threadsafe!
+ config.eager_load = true
+ config.cache_classes = true
RUBY
use_frameworks []
@@ -175,22 +173,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|
View
4 railties/test/application/middleware_test.rb
@@ -87,8 +87,8 @@ def app
assert !middleware.include?("ActiveRecord::QueryCache")
end
- test "removes lock if allow concurrency is set" do
- add_to_config "config.allow_concurrency = true"
+ test "removes lock if cache classes is set" do
+ add_to_config "config.cache_classes = true"
boot!
assert !middleware.include?("Rack::Lock")
end
View
23 railties/test/application/rake_test.rb
@@ -55,6 +55,29 @@ def test_initializers_are_executed_in_rake_tasks
assert_match "Doing something...", output
end
+ def test_does_not_explode_when_accessing_a_model_with_eager_load
+ add_to_config <<-RUBY
+ config.eager_load = true
+
+ rake_tasks do
+ task :do_nothing => :environment do
+ Hello.new.world
+ end
+ end
+ RUBY
+
+ app_file "app/models/hello.rb", <<-RUBY
+ class Hello
+ def world
+ puts "Hello world"
+ end
+ end
+ RUBY
+
+ output = Dir.chdir(app_path){ `rake do_nothing` }
+ assert_match "Hello world", output
+ end
+
def test_code_statistics_sanity
assert_match "Code LOC: 5 Test LOC: 0 Code to Test Ratio: 1:0.0",
Dir.chdir(app_path){ `rake stats` }
View
2 railties/test/isolation/abstract_unit.rb
@@ -12,7 +12,6 @@
require 'minitest/autorun'
require 'active_support/test_case'
-# TODO: Remove setting this magic constant
RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..")
# These files do not require any others and are needed
@@ -118,6 +117,7 @@ def build_app(options = {})
end
add_to_config <<-RUBY
+ config.eager_load = false
config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
config.session_store :cookie_store, :key => "_myapp_session"
config.active_support.deprecation = :log

0 comments on commit 6bef146

Please sign in to comment.
Something went wrong with that request. Please try again.