Simplify the action endpoint:

* Remove ActionEndpoint in favor of passing a block to MiddlewareStack
  * Always create a Request; the performance win of RackDelegation is around
    the response; the Request object hit is limited to a single object allocation
  * #dispatch takes a Request
This commit is contained in:
Carlhuda 2010-03-08 16:49:47 -08:00
parent 146a5305d5
commit 056042eb82
4 changed files with 17 additions and 31 deletions

View File

@ -34,7 +34,8 @@ module ActionController
# and response object available. You might wish to control the # and response object available. You might wish to control the
# environment and response manually for performance reasons. # environment and response manually for performance reasons.
attr_internal :status, :headers, :content_type, :response attr_internal :status, :headers, :content_type, :response, :request
delegate :session, :to => "@_request"
def initialize(*) def initialize(*)
@_headers = {} @_headers = {}
@ -66,8 +67,9 @@ module ActionController
end end
# :api: private # :api: private
def dispatch(name, env) def dispatch(name, request)
@_env = env @_request = request
@_env = request.env
@_env['action_controller.instance'] = self @_env['action_controller.instance'] = self
process(name) process(name)
to_a to_a
@ -78,26 +80,6 @@ module ActionController
response ? response.to_a : [status, headers, response_body] response ? response.to_a : [status, headers, response_body]
end end
class ActionEndpoint
@@endpoints = Hash.new {|h,k| h[k] = Hash.new {|sh,sk| sh[sk] = {} } }
def self.for(controller, action, stack)
@@endpoints[controller][action][stack] ||= begin
endpoint = new(controller, action)
stack.build(endpoint)
end
end
def initialize(controller, action)
@controller, @action = controller, action
@_formats = [Mime::HTML]
end
def call(env)
@controller.new.dispatch(@action, env)
end
end
class_attribute :middleware_stack class_attribute :middleware_stack
self.middleware_stack = ActionDispatch::MiddlewareStack.new self.middleware_stack = ActionDispatch::MiddlewareStack.new
@ -127,8 +109,10 @@ module ActionController
# #
# ==== Returns # ==== Returns
# Proc:: A rack application # Proc:: A rack application
def self.action(name) def self.action(name, klass = ActionDispatch::Request)
ActionEndpoint.for(self, name, middleware_stack) middleware_stack.build do |env|
new.dispatch(name, klass.new(env))
end
end end
end end
end end

View File

@ -6,14 +6,11 @@ module ActionController
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
delegate :session, :to => "@_request"
delegate :headers, :status=, :location=, :content_type=, delegate :headers, :status=, :location=, :content_type=,
:status, :location, :content_type, :to => "@_response" :status, :location, :content_type, :to => "@_response"
attr_internal :request
end end
def dispatch(action, env) def dispatch(action, request)
@_request = ActionDispatch::Request.new(env)
@_response = ActionDispatch::Response.new @_response = ActionDispatch::Response.new
@_response.request = request @_response.request = request
super super

View File

@ -6,7 +6,8 @@ module ActionController
end end
def call(env) def call(env)
@controller.build(@app).dispatch(:index, env) request = ActionDispatch::Request.new(env)
@controller.build(@app).dispatch(:index, request)
end end
end end

View File

@ -122,7 +122,11 @@ module ActionDispatch
find_all { |middleware| middleware.active? } find_all { |middleware| middleware.active? }
end end
def build(app) def build(app = nil, &blk)
app ||= blk
raise "MiddlewareStack#build requires an app" unless app
active.reverse.inject(app) { |a, e| e.build(a) } active.reverse.inject(app) { |a, e| e.build(a) }
end end
end end