mirror of
https://github.com/github/rails.git
synced 2026-01-30 16:58:15 -05:00
Add Dispatcher.to_prepare and config.to_prepare to provide a pre-request hook.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4686 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
*SVN*
|
||||
|
||||
* Add Dispatcher.to_prepare and config.to_prepare to provide a pre-request hook. [Nicholas Seckar]
|
||||
|
||||
* Tweak the Rails load order so observers are loaded after plugins, and reloaded in development mode. Closed #5279. [Rick Olson]
|
||||
|
||||
* Added that you can change the web server port in config/lighttpd.conf from script/server --port/-p #5465 [mats@imediatec.co.uk]
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
# to the appropriate controller and action. It also takes care of resetting
|
||||
# the environment (when Dependencies.load? is true) after each request.
|
||||
class Dispatcher
|
||||
|
||||
class << self
|
||||
|
||||
# Dispatch the given CGI request, using the given session options, and
|
||||
@@ -54,11 +55,36 @@ class Dispatcher
|
||||
# to restart the server (WEBrick, FastCGI, etc.).
|
||||
def reset_application!
|
||||
Dependencies.clear
|
||||
ActiveRecord::Base.reset
|
||||
ActiveRecord::Base.reset if defined?(ActiveRecord)
|
||||
Class.remove_class(*Reloadable.reloadable_classes)
|
||||
end
|
||||
|
||||
|
||||
# Add a preparation callback. Preparation callbacks are run before every
|
||||
# request in development mode, and before the first request in production
|
||||
# mode.
|
||||
#
|
||||
# An optional identifier may be supplied for the callback. If provided,
|
||||
# to_prepare may be called again with the same identifier to replace the
|
||||
# existing callback. Passing an identifier is a suggested practice if the
|
||||
# code adding a preparation block may be reloaded.
|
||||
def to_prepare(identifier = nil, &block)
|
||||
unless identifier.nil?
|
||||
callback = preparation_callbacks.detect { |ident, _| ident == identifier }
|
||||
if callback # Already registered: update the existing callback
|
||||
callback[-1] = block
|
||||
return
|
||||
end
|
||||
end
|
||||
preparation_callbacks << [identifier, block]
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :preparation_callbacks, :preparation_callbacks_run
|
||||
alias_method :preparation_callbacks_run?, :preparation_callbacks_run
|
||||
|
||||
# CGI.new plus exception handling. CGI#read_multipart raises EOFError
|
||||
# if body.empty? or body.size != Content-Length and raises ArgumentError
|
||||
# if Content-Length is non-integer.
|
||||
@@ -67,10 +93,15 @@ class Dispatcher
|
||||
end
|
||||
|
||||
def prepare_application
|
||||
ActionController::Routing::Routes.reload if Dependencies.load?
|
||||
if Dependencies.load?
|
||||
ActionController::Routing::Routes.reload
|
||||
self.preparation_callbacks_run = false
|
||||
end
|
||||
|
||||
prepare_breakpoint
|
||||
require_dependency('application.rb') unless Object.const_defined?(:ApplicationController)
|
||||
ActiveRecord::Base.verify_active_connections!
|
||||
ActiveRecord::Base.verify_active_connections! if defined?(ActiveRecord)
|
||||
run_preparation_callbacks
|
||||
end
|
||||
|
||||
def reset_after_dispatch
|
||||
@@ -87,6 +118,12 @@ class Dispatcher
|
||||
nil
|
||||
end
|
||||
|
||||
def run_preparation_callbacks
|
||||
return if preparation_callbacks_run?
|
||||
preparation_callbacks.each { |_, callback| callback.call }
|
||||
self.preparation_callbacks_run = true
|
||||
end
|
||||
|
||||
# If the block raises, send status code as a last-ditch response.
|
||||
def failsafe_response(output, status, exception = nil)
|
||||
yield
|
||||
@@ -117,4 +154,8 @@ class Dispatcher
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.preparation_callbacks = []
|
||||
self.preparation_callbacks_run = false
|
||||
|
||||
end
|
||||
|
||||
@@ -294,6 +294,13 @@ module Rails
|
||||
configuration.after_initialize_block.call if configuration.after_initialize_block
|
||||
end
|
||||
|
||||
# Add a preparation callback that will run before every request in development
|
||||
# mode, or before the first request in production.
|
||||
#
|
||||
# See Dispatcher#to_prepare.
|
||||
def to_prepare(&callback)
|
||||
Dispatcher.to_prepare(&callback)
|
||||
end
|
||||
|
||||
protected
|
||||
# Return a list of plugin paths within base_path. A plugin path is
|
||||
|
||||
@@ -24,6 +24,8 @@ class DispatcherTest < Test::Unit::TestCase
|
||||
def setup
|
||||
@output = StringIO.new
|
||||
ENV['REQUEST_METHOD'] = "GET"
|
||||
Dispatcher.send(:preparation_callbacks).clear
|
||||
Dispatcher.send(:preparation_callbacks_run=, false)
|
||||
end
|
||||
|
||||
def teardown
|
||||
@@ -84,6 +86,53 @@ class DispatcherTest < Test::Unit::TestCase
|
||||
ensure
|
||||
$stdin = old_stdin
|
||||
end
|
||||
|
||||
def test_preparation_callbacks
|
||||
Object.const_set :ApplicationController, nil
|
||||
old_mechanism = Dependencies.mechanism
|
||||
|
||||
a = b = c = nil
|
||||
Dispatcher.to_prepare { a = b = c = 1 }
|
||||
Dispatcher.to_prepare { b = c = 2 }
|
||||
Dispatcher.to_prepare { c = 3 }
|
||||
|
||||
Dispatcher.send :prepare_application
|
||||
|
||||
assert_equal 1, a
|
||||
assert_equal 2, b
|
||||
assert_equal 3, c
|
||||
|
||||
# When mechanism is :load, perform the callbacks each request:
|
||||
Dependencies.mechanism = :load
|
||||
a = b = c = nil
|
||||
Dispatcher.send :prepare_application
|
||||
assert_equal 1, a
|
||||
assert_equal 2, b
|
||||
assert_equal 3, c
|
||||
|
||||
# But when not :load, make sure they are only run once
|
||||
a = b = c = nil
|
||||
Dependencies.mechanism = :not_load
|
||||
Dispatcher.send :prepare_application
|
||||
assert_equal nil, a || b || c
|
||||
ensure
|
||||
Dependencies.mechanism = old_mechanism
|
||||
Object.send :remove_const, :ApplicationController
|
||||
end
|
||||
|
||||
def test_to_prepare_with_identifier_replaces
|
||||
Object.const_set :ApplicationController, nil
|
||||
|
||||
a = b = nil
|
||||
Dispatcher.to_prepare(:unique_id) { a = b = 1 }
|
||||
Dispatcher.to_prepare(:unique_id) { a = 2 }
|
||||
|
||||
Dispatcher.send :prepare_application
|
||||
assert_equal 2, a
|
||||
assert_equal nil, b
|
||||
ensure
|
||||
Object.send :remove_const, :ApplicationController
|
||||
end
|
||||
|
||||
private
|
||||
def dispatch
|
||||
|
||||
Reference in New Issue
Block a user