1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow users to choose when to eager_load the application or not.

Previously, the eager load behavior was mostly coupled to
config.cache_classes, however this was suboptimal since in
some environments a developer may want to cache classes but
not necessarily load them all on boot (for example, test env).

This pull request also promotes the use of config.eager_load
set to true by default in production. In the majority of the
cases, this is the behavior you want since it will copy most
of your app into memory on boot (which was also the previous
behavior).

Finally, this fix a long standing Rails bug where it was
impossible to access a model in a rake task when Rails was
set as thread safe.
This commit is contained in:
José Valim 2012-08-01 15:07:01 +02:00
parent df1a5e492a
commit e6747d87f3
9 changed files with 67 additions and 8 deletions

View file

@ -83,6 +83,13 @@ module Rails
@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
@ -216,8 +223,9 @@ module Rails
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

View file

@ -13,6 +13,20 @@ module Rails
require "active_support/all" unless config.active_support.bare
end
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:
* 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
# 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.
@ -60,7 +74,6 @@ module Rails
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 file

@ -7,7 +7,7 @@ module Rails
class Configuration < ::Rails::Engine::Configuration
attr_accessor :allow_concurrency, :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,
:serve_static_assets, :ssl_options, :static_cache_control, :session_options,
@ -24,7 +24,6 @@ module Rails
@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 +44,7 @@ module Rails
@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
@ -98,7 +98,7 @@ module Rails
def threadsafe!
@preload_frameworks = true
@cache_classes = true
@dependency_loading = false
@eager_load = true
@allow_concurrency = true
self
end

View file

@ -50,7 +50,7 @@ module Rails
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!
end
@ -91,7 +91,7 @@ module Rails
# 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 file

@ -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 file

@ -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 file

@ -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 file

@ -55,6 +55,30 @@ module ApplicationTests
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` }
puts output
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 file

@ -12,7 +12,6 @@ require 'bundler/setup'
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 @@ module TestHelpers
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