1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
module ActionController
# Dispatches requests to the appropriate controller and takes care of
# reloading the app after each request when Dependencies.load? is true.
class Dispatcher
class << self
def define_dispatcher_callbacks(cache_classes)
unless cache_classes
# Development mode callbacks
before_dispatch :reload_application
after_dispatch :cleanup_application
end
if defined?(ActiveRecord)
after_dispatch :checkin_connections
to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
end
after_dispatch :flush_logger if Base.logger && Base.logger.respond_to?(:flush)
to_prepare do
I18n.reload!
end
end
# DEPRECATE: Remove CGI support
def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout)
new(output).dispatch_cgi(cgi, session_options)
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)
@prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier)
@prepare_dispatch_callbacks.replace_or_append!(callback)
end
end
cattr_accessor :middleware
self.middleware = MiddlewareStack.new do |middleware|
middleware.use "ActionController::Lock", :if => lambda {
!ActionController::Base.allow_concurrency
}
middleware.use "ActionController::Failsafe"
["ActionController::Session::CookieStore",
"ActionController::Session::MemCacheStore",
"ActiveRecord::SessionStore"].each do |store|
middleware.use(store, ActionController::Base.session_options,
:if => lambda {
if session_store = ActionController::Base.session_store
session_store.name == store
end
}
)
end
end
include ActiveSupport::Callbacks
define_callbacks :prepare_dispatch, :before_dispatch, :after_dispatch
# DEPRECATE: Remove arguments, since they are only used by CGI
def initialize(output = $stdout, request = nil, response = nil)
@output = output
@app = @@middleware.build(lambda { |env| self.dup._call(env) })
end
def dispatch
begin
run_callbacks :before_dispatch
controller = Routing::Routes.recognize(@request)
controller.process(@request, @response).to_a
rescue Exception => exception
if controller ||= (::ApplicationController rescue Base)
controller.process_with_exception(@request, @response, exception).to_a
else
raise exception
end
ensure
run_callbacks :after_dispatch, :enumerator => :reverse_each
end
end
# DEPRECATE: Remove CGI support
def dispatch_cgi(cgi, session_options)
CGIHandler.dispatch_cgi(self, cgi, @output)
end
def call(env)
@app.call(env)
end
def _call(env)
@request = RackRequest.new(env)
@response = RackResponse.new
dispatch
end
def reload_application
# Run prepare callbacks before every request in development mode
run_callbacks :prepare_dispatch
Routing::Routes.reload
ActionView::Helpers::AssetTagHelper::AssetTag::Cache.clear
end
# Cleanup the application by clearing out loaded classes so they can
# be reloaded on the next request without restarting the server.
def cleanup_application
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
ActiveSupport::Dependencies.clear
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
end
def flush_logger
Base.logger.flush
end
def checkin_connections
# Don't return connection (and peform implicit rollback) if this request is a part of integration test
# TODO: This callback should have direct access to env
return if @request.key?("rack.test")
ActiveRecord::Base.clear_active_connections!
end
end
end
|