Class: ActionController::Dispatcher

Inherits:
Object
  • Object
show all
Includes:
ActiveSupport::Callbacks
Defined in:
lib/action_controller/dispatcher.rb

Overview

Dispatches requests to the appropriate controller and takes care of reloading the app after each request when Dependencies.load? is true.

Constant Summary collapse

@@guard =
Mutex.new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(output, request = nil, response = nil) ⇒ Dispatcher

Returns a new instance of Dispatcher.



99
100
101
# File 'lib/action_controller/dispatcher.rb', line 99

def initialize(output, request = nil, response = nil)
  @output, @request, @response = output, request, response
end

Class Method Details

.define_dispatcher_callbacks(cache_classes) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/action_controller/dispatcher.rb', line 8

def define_dispatcher_callbacks(cache_classes)
  unless cache_classes
    # Development mode callbacks
    before_dispatch :reload_application
    after_dispatch :cleanup_application
  end

  # Common callbacks
  to_prepare :load_application_controller do
    begin
      require_dependency 'application' unless defined?(::ApplicationController)
    rescue LoadError => error
      raise unless error.message =~ /application\.rb/
    end
  end

  if defined?(ActiveRecord)
    before_dispatch { ActiveRecord::Base.verify_active_connections! }
    to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
  end

  after_dispatch :flush_logger if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush)
end

.dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout) ⇒ Object

Backward-compatible class method takes CGI-specific args. Deprecated in favor of Dispatcher.new(output, request, response).dispatch.



34
35
36
# File 'lib/action_controller/dispatcher.rb', line 34

def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout)
  new(output).dispatch_cgi(cgi, session_options)
end

.failsafe_response(fallback_output, status, originating_exception = nil) ⇒ Object

If the block raises, send status code as a last-ditch response.



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/action_controller/dispatcher.rb', line 53

def failsafe_response(fallback_output, status, originating_exception = nil)
  yield
rescue Exception => exception
  begin
    log_failsafe_exception(status, originating_exception || exception)
    body = failsafe_response_body(status)
    fallback_output.write "Status: #{status}\r\nContent-Type: text/html\r\n\r\n#{body}"
    nil
  rescue Exception => failsafe_error # Logger or IO errors
    $stderr.puts "Error during failsafe response: #{failsafe_error}"
    $stderr.puts "(originally #{originating_exception})" if originating_exception
  end
end

.to_prepare(identifier = nil, &block) ⇒ Object

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.



46
47
48
49
50
# File 'lib/action_controller/dispatcher.rb', line 46

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 | callback
end

Instance Method Details

#cleanup_applicationObject

Cleanup the application by clearing out loaded classes so they can be reloaded on the next request without restarting the server.



136
137
138
139
140
# File 'lib/action_controller/dispatcher.rb', line 136

def cleanup_application
  ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
  ActiveSupport::Dependencies.clear
  ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
end

#dispatchObject



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/action_controller/dispatcher.rb', line 103

def dispatch
  @@guard.synchronize do
    begin
      run_callbacks :before_dispatch
      handle_request
    rescue Exception => exception
      failsafe_rescue exception
    ensure
      run_callbacks :after_dispatch, :enumerator => :reverse_each
    end
  end
end

#dispatch_cgi(cgi, session_options) ⇒ Object



116
117
118
119
120
121
122
123
124
# File 'lib/action_controller/dispatcher.rb', line 116

def dispatch_cgi(cgi, session_options)
  if cgi ||= self.class.failsafe_response(@output, '400 Bad Request') { CGI.new }
    @request = CgiRequest.new(cgi, session_options)
    @response = CgiResponse.new(cgi)
    dispatch
  end
rescue Exception => exception
  failsafe_rescue exception
end

#flush_loggerObject



142
143
144
# File 'lib/action_controller/dispatcher.rb', line 142

def flush_logger
  RAILS_DEFAULT_LOGGER.flush
end

#reload_applicationObject



126
127
128
129
130
131
132
# File 'lib/action_controller/dispatcher.rb', line 126

def reload_application
  # Run prepare callbacks before every request in development mode
  run_callbacks :prepare_dispatch

  Routing::Routes.reload
  ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading
end