提交 69c049f5 编写于 作者: J Joshua Peek

Move development mode reloading up the stack to avoid issues with class reloading in middleware

上级 53fe301a
...@@ -59,6 +59,7 @@ def self.load_all! ...@@ -59,6 +59,7 @@ def self.load_all!
autoload :ParamsParser, 'action_controller/params_parser' autoload :ParamsParser, 'action_controller/params_parser'
autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes' autoload :PolymorphicRoutes, 'action_controller/polymorphic_routes'
autoload :RecordIdentifier, 'action_controller/record_identifier' autoload :RecordIdentifier, 'action_controller/record_identifier'
autoload :Reloader, 'action_controller/reloader'
autoload :Request, 'action_controller/request' autoload :Request, 'action_controller/request'
autoload :RequestForgeryProtection, 'action_controller/request_forgery_protection' autoload :RequestForgeryProtection, 'action_controller/request_forgery_protection'
autoload :Rescue, 'action_controller/rescue' autoload :Rescue, 'action_controller/rescue'
......
...@@ -5,8 +5,9 @@ class Dispatcher ...@@ -5,8 +5,9 @@ class Dispatcher
class << self class << self
def define_dispatcher_callbacks(cache_classes) def define_dispatcher_callbacks(cache_classes)
unless cache_classes unless cache_classes
# Development mode callbacks unless self.middleware.include?(Reloader)
before_dispatch :reload_application self.middleware.insert_after(Failsafe, Reloader)
end
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
end end
...@@ -41,6 +42,30 @@ def to_prepare(identifier = nil, &block) ...@@ -41,6 +42,30 @@ def to_prepare(identifier = nil, &block)
callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier) callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier)
@prepare_dispatch_callbacks.replace_or_append!(callback) @prepare_dispatch_callbacks.replace_or_append!(callback)
end end
def run_prepare_callbacks
if defined?(Rails) && Rails.logger
logger = Rails.logger
else
logger = Logger.new($stderr)
end
new(logger).send :run_callbacks, :prepare_dispatch
end
def reload_application
# Run prepare callbacks before every request in development mode
run_prepare_callbacks
Routing::Routes.reload
end
def cleanup_application
# Cleanup the application before processing the current request.
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
ActiveSupport::Dependencies.clear
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
end
end end
cattr_accessor :middleware cattr_accessor :middleware
...@@ -87,18 +112,6 @@ def _call(env) ...@@ -87,18 +112,6 @@ def _call(env)
dispatch dispatch
end end
def reload_application
# Cleanup the application before processing the current request.
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
ActiveSupport::Dependencies.clear
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
# Run prepare callbacks before every request in development mode
run_callbacks :prepare_dispatch
Routing::Routes.reload
end
def flush_logger def flush_logger
Base.logger.flush Base.logger.flush
end end
......
module ActionController
class Reloader
def initialize(app)
@app = app
end
def call(env)
Dispatcher.reload_application
@app.call(env)
ensure
Dispatcher.cleanup_application
end
end
end
...@@ -6,14 +6,17 @@ class DispatcherTest < Test::Unit::TestCase ...@@ -6,14 +6,17 @@ class DispatcherTest < Test::Unit::TestCase
def setup def setup
ENV['REQUEST_METHOD'] = 'GET' ENV['REQUEST_METHOD'] = 'GET'
Dispatcher.middleware = ActionController::MiddlewareStack.new do |middleware|
middlewares = File.expand_path(File.join(File.dirname(__FILE__), "../../lib/action_controller/middlewares.rb"))
middleware.instance_eval(File.read(middlewares))
end
# Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks # Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks
Dispatcher.instance_variable_set("@prepare_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) Dispatcher.instance_variable_set("@prepare_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
Dispatcher.instance_variable_set("@before_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) Dispatcher.instance_variable_set("@before_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
Dispatcher.instance_variable_set("@after_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new) Dispatcher.instance_variable_set("@after_dispatch_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
Dispatcher.stubs(:require_dependency) Dispatcher.stubs(:require_dependency)
@dispatcher = Dispatcher.new
end end
def teardown def teardown
...@@ -65,7 +68,7 @@ def test_prepare_callbacks ...@@ -65,7 +68,7 @@ def test_prepare_callbacks
assert_nil a || b || c assert_nil a || b || c
# Run callbacks # Run callbacks
@dispatcher.send :run_callbacks, :prepare_dispatch Dispatcher.run_prepare_callbacks
assert_equal 1, a assert_equal 1, a
assert_equal 2, b assert_equal 2, b
...@@ -82,7 +85,7 @@ def test_to_prepare_with_identifier_replaces ...@@ -82,7 +85,7 @@ def test_to_prepare_with_identifier_replaces
Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 } Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 }
Dispatcher.to_prepare(:unique_id) { |*args| a = 2 } Dispatcher.to_prepare(:unique_id) { |*args| a = 2 }
@dispatcher.send :run_callbacks, :prepare_dispatch Dispatcher.run_prepare_callbacks
assert_equal 2, a assert_equal 2, a
assert_equal nil, b assert_equal nil, b
end end
...@@ -91,7 +94,7 @@ def test_to_prepare_with_identifier_replaces ...@@ -91,7 +94,7 @@ def test_to_prepare_with_identifier_replaces
def dispatch(cache_classes = true) def dispatch(cache_classes = true)
ActionController::Routing::RouteSet.any_instance.stubs(:call).returns([200, {}, 'response']) ActionController::Routing::RouteSet.any_instance.stubs(:call).returns([200, {}, 'response'])
Dispatcher.define_dispatcher_callbacks(cache_classes) Dispatcher.define_dispatcher_callbacks(cache_classes)
@dispatcher.call({}) Dispatcher.new.call({})
end end
def assert_subclasses(howmany, klass, message = klass.subclasses.inspect) def assert_subclasses(howmany, klass, message = klass.subclasses.inspect)
......
...@@ -24,7 +24,6 @@ def new_session ...@@ -24,7 +24,6 @@ def new_session
#reloads the environment #reloads the environment
def reload! def reload!
puts "Reloading..." puts "Reloading..."
dispatcher = ActionController::Dispatcher.new($stdout) Dispatcher.reload_application
dispatcher.reload_application
true true
end end
...@@ -583,7 +583,7 @@ def prepare_dispatcher ...@@ -583,7 +583,7 @@ def prepare_dispatcher
return unless configuration.frameworks.include?(:action_controller) return unless configuration.frameworks.include?(:action_controller)
require 'dispatcher' unless defined?(::Dispatcher) require 'dispatcher' unless defined?(::Dispatcher)
Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) Dispatcher.define_dispatcher_callbacks(configuration.cache_classes)
Dispatcher.new(Rails.logger).send :run_callbacks, :prepare_dispatch Dispatcher.run_prepare_callbacks
end end
def disable_dependency_loading def disable_dependency_loading
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册