提交 e6747d87 编写于 作者: J José Valim

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.
上级 df1a5e49
......@@ -83,6 +83,13 @@ 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
......@@ -216,8 +223,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
......
......@@ -13,6 +13,20 @@ module Bootstrap
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 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
......
......@@ -7,7 +7,7 @@ class Application
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 @@ def initialize(*)
@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 @@ 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
......@@ -98,7 +98,7 @@ def paths
def threadsafe!
@preload_frameworks = true
@cache_classes = true
@dependency_loading = false
@eager_load = true
@allow_concurrency = true
self
end
......
......@@ -50,7 +50,7 @@ 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!
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
......
......@@ -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
......
......@@ -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
......
......@@ -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"
......
......@@ -55,6 +55,30 @@ 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` }
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` }
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册