Skip to content
This repository
Browse code

Reduce the cost of using ActionController::Http significantly by:

  * Removing the dependency on AD::Request and AD::Response
  * Moving the logic for the request and response object
    into a new module that is included by default.
  * Changing Renderer and Redirector to use self.headers,
    self.content_type, and self.status, which have very basic
    default implementations on AC::Http. When RackConvenience
    is included (which it is by default on AC::Base), the full
    Request/Response logic is used instead of the simple logic.
  • Loading branch information...
commit 6bbe965ccdcef2d7e713e65175722718d325b2bd 1 parent 311d686
authored May 27, 2009
1  actionpack/lib/action_controller/new_base.rb
@@ -4,6 +4,7 @@ module ActionController
4 4
   autoload :HideActions,          "action_controller/new_base/hide_actions"
5 5
   autoload :Http,                 "action_controller/new_base/http"
6 6
   autoload :Layouts,              "action_controller/new_base/layouts"
  7
+  autoload :RackConvenience,      "action_controller/new_base/rack_convenience"
7 8
   autoload :Rails2Compatibility,  "action_controller/new_base/compatibility"
8 9
   autoload :Redirector,           "action_controller/new_base/redirector"
9 10
   autoload :Renderer,             "action_controller/new_base/renderer"
1  actionpack/lib/action_controller/new_base/base.rb
@@ -14,6 +14,7 @@ class Base < Http
14 14
     include ActionController::Renderers::All
15 15
     include ActionController::Layouts
16 16
     include ActionController::ConditionalGet
  17
+    include ActionController::RackConvenience
17 18
 
18 19
     # Legacy modules
19 20
     include SessionManagement
3  actionpack/lib/action_controller/new_base/conditional_get.rb
... ...
@@ -1,5 +1,8 @@
1 1
 module ActionController
2 2
   module ConditionalGet
  3
+    extend ActiveSupport::DependencyModule
  4
+
  5
+    depends_on RackConvenience
3 6
     
4 7
     # Sets the etag, last_modified, or both on the response and renders a
5 8
     # "304 Not Modified" response if the request is already fresh.
42  actionpack/lib/action_controller/new_base/http.rb
@@ -6,7 +6,7 @@ class Http < AbstractController::Base
6 6
     abstract!
7 7
     
8 8
     # :api: public
9  
-    attr_internal :request, :response, :params
  9
+    attr_internal :params, :env
10 10
 
11 11
     # :api: public
12 12
     def self.controller_name
@@ -36,32 +36,48 @@ def self.call(env)
36 36
       controller.call(env).to_rack
37 37
     end
38 38
     
39  
-    delegate :headers, :to => "@_response"
  39
+    # The details below can be overridden to support a specific
  40
+    # Request and Response object. The default ActionController::Base
  41
+    # implementation includes RackConvenience, which makes a request
  42
+    # and response object available. You might wish to control the
  43
+    # environment and response manually for performance reasons.
40 44
 
41  
-    def params
42  
-      @_params ||= @_request.parameters
  45
+    attr_internal :status, :headers, :content_type
  46
+
  47
+    def initialize(*)
  48
+      @_headers = {}
  49
+      super
  50
+    end
  51
+
  52
+    # Basic implements for content_type=, location=, and headers are
  53
+    # provided to reduce the dependency on the RackConvenience module
  54
+    # in Renderer and Redirector.
  55
+
  56
+    def content_type=(type)
  57
+      headers["Content-Type"] = type.to_s
  58
+    end
  59
+
  60
+    def location=(url)
  61
+      headers["Location"] = url
43 62
     end
44 63
     
45 64
     # :api: private
46 65
     def call(name, env)
47  
-      @_request = ActionDispatch::Request.new(env)
48  
-      @_response = ActionDispatch::Response.new
49  
-      @_response.request = request
  66
+      @_env = env
50 67
       process(name)
51 68
       to_rack
52 69
     end
53 70
     
  71
+    # :api: private
  72
+    def to_rack
  73
+      [status, headers, response_body]
  74
+    end
  75
+
54 76
     def self.action(name)
55 77
       @actions ||= {}
56 78
       @actions[name.to_s] ||= proc do |env|
57 79
         new.call(name, env)
58 80
       end
59 81
     end
60  
-    
61  
-    # :api: private
62  
-    def to_rack
63  
-      @_response.prepare!
64  
-      @_response.to_a
65  
-    end
66 82
   end
67 83
 end
34  actionpack/lib/action_controller/new_base/rack_convenience.rb
... ...
@@ -0,0 +1,34 @@
  1
+module ActionController
  2
+  module RackConvenience
  3
+    extend ActiveSupport::DependencyModule
  4
+    
  5
+    included do
  6
+      delegate :headers, :status=, :location=, 
  7
+               :status, :location, :content_type, :to => "@_response"
  8
+      attr_internal :request, :response
  9
+    end
  10
+    
  11
+    def call(name, env)
  12
+      @_request = ActionDispatch::Request.new(env)
  13
+      @_response = ActionDispatch::Response.new
  14
+      @_response.request = request
  15
+      super
  16
+    end
  17
+    
  18
+    def params
  19
+      @_params ||= @_request.parameters
  20
+    end
  21
+    
  22
+    # :api: private
  23
+    def to_rack
  24
+      @_response.prepare!
  25
+      @_response.to_a
  26
+    end
  27
+    
  28
+    def response_body=(body)
  29
+      response.body = body if response
  30
+      super
  31
+    end
  32
+    
  33
+  end
  34
+end
4  actionpack/lib/action_controller/new_base/redirector.rb
@@ -11,8 +11,8 @@ module Redirector
11 11
     def redirect_to(url, status) #:doc:
12 12
       raise AbstractController::DoubleRenderError if response_body
13 13
       logger.info("Redirected to #{url}") if logger && logger.info?
14  
-      response.status = status
15  
-      response.location = url.gsub(/[\r\n]/, '')
  14
+      self.status = status
  15
+      self.location = url.gsub(/[\r\n]/, '')
16 16
       self.response_body = "<html><body>You are being <a href=\"#{CGI.escapeHTML(url)}\">redirected</a>.</body></html>"
17 17
     end
18 18
   end
8  actionpack/lib/action_controller/new_base/render_options.rb
@@ -57,7 +57,7 @@ module Json
57 57
       def _render_json(json, options)
58 58
         json = ActiveSupport::JSON.encode(json) unless json.respond_to?(:to_str)
59 59
         json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
60  
-        response.content_type ||= Mime::JSON
  60
+        self.content_type ||= Mime::JSON
61 61
         self.response_body = json
62 62
       end      
63 63
     end
@@ -67,7 +67,7 @@ module Js
67 67
       register_renderer :js
68 68
 
69 69
       def _render_js(js, options)
70  
-        response.content_type ||= Mime::JS
  70
+        self.content_type ||= Mime::JS
71 71
         self.response_body = js
72 72
       end
73 73
     end
@@ -77,7 +77,7 @@ module Xml
77 77
       register_renderer :xml
78 78
 
79 79
       def _render_xml(xml, options)
80  
-        response.content_type ||= Mime::XML
  80
+        self.content_type ||= Mime::XML
81 81
         self.response_body  = xml.respond_to?(:to_xml) ? xml.to_xml : xml
82 82
       end
83 83
     end
@@ -88,7 +88,7 @@ module Rjs
88 88
 
89 89
       def _render_update(proc, options)
90 90
         generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(_action_view, &proc)
91  
-        response.content_type = Mime::JS
  91
+        self.content_type = Mime::JS
92 92
         self.response_body = generator.to_s
93 93
       end
94 94
     end
13  actionpack/lib/action_controller/new_base/renderer.rb
@@ -8,16 +8,11 @@ def process_action(*)
8 8
       self.formats = request.formats.map {|x| x.to_sym}
9 9
       super
10 10
     end
11  
-    
12  
-    def response_body=(body)
13  
-      response.body = body if response
14  
-      super
15  
-    end
16 11
 
17 12
     def render(options)
18 13
       super
19 14
       options[:_template] ||= _action_view._partial
20  
-      response.content_type ||= begin
  15
+      self.content_type ||= begin
21 16
         mime = options[:_template].mime_type
22 17
         formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first)
23 18
       end
@@ -76,9 +71,9 @@ def _render_partial(partial, options)
76 71
   
77 72
     def _process_options(options)
78 73
       status, content_type, location = options.values_at(:status, :content_type, :location)
79  
-      response.status = status if status
80  
-      response.content_type = content_type if content_type
81  
-      response.headers["Location"] = url_for(location) if location
  74
+      self.status = status if status
  75
+      self.content_type = content_type if content_type
  76
+      self.headers["Location"] = url_for(location) if location
82 77
     end
83 78
   end
84 79
 end
4  actionpack/lib/action_controller/new_base/session.rb
... ...
@@ -1,5 +1,9 @@
1 1
 module ActionController
2 2
   module Session
  3
+    extend ActiveSupport::DependencyModule
  4
+
  5
+    depends_on RackConvenience
  6
+
3 7
     def session
4 8
       @_request.session
5 9
     end
2  actionpack/lib/action_controller/new_base/testing.rb
@@ -2,6 +2,8 @@ module ActionController
2 2
   module Testing
3 3
     extend ActiveSupport::DependencyModule
4 4
 
  5
+    depends_on RackConvenience
  6
+
5 7
     # OMG MEGA HAX
6 8
     def process_with_new_base_test(request, response)
7 9
       @_request = request
4  actionpack/lib/action_controller/new_base/url_for.rb
... ...
@@ -1,5 +1,9 @@
1 1
 module ActionController
2 2
   module UrlFor
  3
+    extend ActiveSupport::DependencyModule
  4
+
  5
+    depends_on RackConvenience
  6
+
3 7
     def process_action(*)
4 8
       initialize_current_url
5 9
       super

0 notes on commit 6bbe965

Please sign in to comment.
Something went wrong with that request. Please try again.