actionpack 3.0.20 → 3.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (161) hide show
  1. data/CHANGELOG +88 -142
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +5 -6
  4. data/lib/abstract_controller.rb +1 -0
  5. data/lib/abstract_controller/asset_paths.rb +2 -2
  6. data/lib/abstract_controller/base.rb +24 -19
  7. data/lib/abstract_controller/callbacks.rb +19 -19
  8. data/lib/abstract_controller/helpers.rb +11 -13
  9. data/lib/abstract_controller/layouts.rb +4 -5
  10. data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
  11. data/lib/abstract_controller/rendering.rb +34 -31
  12. data/lib/abstract_controller/url_for.rb +27 -0
  13. data/lib/abstract_controller/view_paths.rb +31 -6
  14. data/lib/action_controller.rb +5 -3
  15. data/lib/action_controller/base.rb +15 -16
  16. data/lib/action_controller/caching.rb +2 -2
  17. data/lib/action_controller/caching/actions.rb +11 -12
  18. data/lib/action_controller/caching/fragments.rb +41 -19
  19. data/lib/action_controller/caching/pages.rb +3 -9
  20. data/lib/action_controller/caching/sweeping.rb +0 -1
  21. data/lib/action_controller/deprecated.rb +1 -1
  22. data/lib/action_controller/log_subscriber.rb +1 -1
  23. data/lib/action_controller/metal.rb +78 -20
  24. data/lib/action_controller/metal/compatibility.rb +0 -9
  25. data/lib/action_controller/metal/conditional_get.rb +9 -9
  26. data/lib/action_controller/metal/data_streaming.rb +145 -0
  27. data/lib/action_controller/metal/force_ssl.rb +35 -0
  28. data/lib/action_controller/metal/head.rb +1 -1
  29. data/lib/action_controller/metal/helpers.rb +37 -44
  30. data/lib/action_controller/metal/hide_actions.rb +2 -3
  31. data/lib/action_controller/metal/http_authentication.rb +41 -38
  32. data/lib/action_controller/metal/implicit_render.rb +13 -13
  33. data/lib/action_controller/metal/instrumentation.rb +2 -2
  34. data/lib/action_controller/metal/mime_responds.rb +25 -19
  35. data/lib/action_controller/metal/params_wrapper.rb +224 -0
  36. data/lib/action_controller/metal/redirecting.rb +6 -2
  37. data/lib/action_controller/metal/renderers.rb +50 -36
  38. data/lib/action_controller/metal/rendering.rb +34 -25
  39. data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
  40. data/lib/action_controller/metal/responder.rb +47 -12
  41. data/lib/action_controller/metal/streaming.rb +244 -138
  42. data/lib/action_controller/metal/testing.rb +0 -9
  43. data/lib/action_controller/metal/url_for.rb +12 -14
  44. data/lib/action_controller/railtie.rb +19 -37
  45. data/lib/action_controller/railties/paths.rb +24 -0
  46. data/lib/action_controller/record_identifier.rb +4 -10
  47. data/lib/action_controller/test_case.rb +36 -19
  48. data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
  49. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
  50. data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
  51. data/lib/action_dispatch.rb +4 -1
  52. data/lib/action_dispatch/http/cache.rb +5 -32
  53. data/lib/action_dispatch/http/filter_parameters.rb +3 -1
  54. data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
  55. data/lib/action_dispatch/http/mime_type.rb +45 -5
  56. data/lib/action_dispatch/http/rack_cache.rb +58 -0
  57. data/lib/action_dispatch/http/request.rb +27 -41
  58. data/lib/action_dispatch/http/response.rb +56 -54
  59. data/lib/action_dispatch/http/upload.rb +1 -11
  60. data/lib/action_dispatch/http/url.rb +102 -42
  61. data/lib/action_dispatch/middleware/callbacks.rb +8 -25
  62. data/lib/action_dispatch/middleware/closed_error.rb +7 -0
  63. data/lib/action_dispatch/middleware/cookies.rb +37 -15
  64. data/lib/action_dispatch/middleware/flash.rb +80 -11
  65. data/lib/action_dispatch/middleware/params_parser.rb +2 -2
  66. data/lib/action_dispatch/middleware/reloader.rb +76 -0
  67. data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
  68. data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
  69. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
  70. data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
  71. data/lib/action_dispatch/middleware/stack.rb +50 -17
  72. data/lib/action_dispatch/middleware/static.rb +41 -29
  73. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
  74. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  75. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
  76. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
  77. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
  78. data/lib/action_dispatch/railtie.rb +8 -0
  79. data/lib/action_dispatch/routing.rb +13 -1
  80. data/lib/action_dispatch/routing/mapper.rb +345 -227
  81. data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
  82. data/lib/action_dispatch/routing/redirection.rb +110 -0
  83. data/lib/action_dispatch/routing/route.rb +15 -13
  84. data/lib/action_dispatch/routing/route_set.rb +116 -90
  85. data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
  86. data/lib/action_dispatch/routing/url_for.rb +25 -1
  87. data/lib/action_dispatch/testing/assertions/response.rb +8 -10
  88. data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
  89. data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
  90. data/lib/action_dispatch/testing/integration.rb +37 -28
  91. data/lib/action_dispatch/testing/performance_test.rb +1 -3
  92. data/lib/action_dispatch/testing/test_process.rb +1 -1
  93. data/lib/action_dispatch/testing/test_request.rb +9 -3
  94. data/lib/action_dispatch/testing/test_response.rb +4 -111
  95. data/lib/action_pack.rb +1 -1
  96. data/lib/action_pack/version.rb +3 -3
  97. data/lib/action_view.rb +39 -24
  98. data/lib/action_view/base.rb +61 -86
  99. data/lib/action_view/buffers.rb +43 -0
  100. data/lib/action_view/context.rb +21 -24
  101. data/lib/action_view/flows.rb +79 -0
  102. data/lib/action_view/helpers.rb +8 -6
  103. data/lib/action_view/helpers/active_model_helper.rb +0 -23
  104. data/lib/action_view/helpers/asset_paths.rb +79 -0
  105. data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
  106. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
  107. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
  108. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
  109. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
  110. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  111. data/lib/action_view/helpers/cache_helper.rb +11 -19
  112. data/lib/action_view/helpers/capture_helper.rb +19 -8
  113. data/lib/action_view/helpers/controller_helper.rb +21 -0
  114. data/lib/action_view/helpers/csrf_helper.rb +22 -4
  115. data/lib/action_view/helpers/date_helper.rb +36 -22
  116. data/lib/action_view/helpers/form_helper.rb +199 -113
  117. data/lib/action_view/helpers/form_options_helper.rb +10 -11
  118. data/lib/action_view/helpers/form_tag_helper.rb +94 -22
  119. data/lib/action_view/helpers/javascript_helper.rb +24 -107
  120. data/lib/action_view/helpers/number_helper.rb +36 -33
  121. data/lib/action_view/helpers/output_safety_helper.rb +38 -0
  122. data/lib/action_view/helpers/record_tag_helper.rb +6 -6
  123. data/lib/action_view/helpers/rendering_helper.rb +90 -0
  124. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  125. data/lib/action_view/helpers/sprockets_helper.rb +69 -0
  126. data/lib/action_view/helpers/tag_helper.rb +34 -12
  127. data/lib/action_view/helpers/text_helper.rb +30 -145
  128. data/lib/action_view/helpers/translation_helper.rb +10 -17
  129. data/lib/action_view/helpers/url_helper.rb +70 -67
  130. data/lib/action_view/locale/en.yml +1 -1
  131. data/lib/action_view/lookup_context.rb +36 -14
  132. data/lib/action_view/{paths.rb → path_set.rb} +9 -8
  133. data/lib/action_view/railtie.rb +12 -4
  134. data/lib/action_view/renderer/abstract_renderer.rb +36 -0
  135. data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
  136. data/lib/action_view/renderer/renderer.rb +54 -0
  137. data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
  138. data/lib/action_view/renderer/template_renderer.rb +74 -0
  139. data/lib/action_view/template.rb +91 -54
  140. data/lib/action_view/template/error.rb +11 -8
  141. data/lib/action_view/template/handler.rb +9 -1
  142. data/lib/action_view/template/handlers.rb +9 -9
  143. data/lib/action_view/template/handlers/builder.rb +4 -4
  144. data/lib/action_view/template/handlers/erb.rb +21 -41
  145. data/lib/action_view/template/resolver.rb +171 -57
  146. data/lib/action_view/template/text.rb +0 -4
  147. data/lib/action_view/test_case.rb +32 -16
  148. data/lib/action_view/testing/resolvers.rb +16 -10
  149. data/lib/sprockets/railtie.rb +100 -0
  150. metadata +162 -140
  151. checksums.yaml +0 -7
  152. data/lib/action_controller/deprecated/base.rb +0 -143
  153. data/lib/action_controller/deprecated/dispatcher.rb +0 -28
  154. data/lib/action_controller/deprecated/url_writer.rb +0 -14
  155. data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
  156. data/lib/action_view/helpers/prototype_helper.rb +0 -851
  157. data/lib/action_view/helpers/raw_output_helper.rb +0 -18
  158. data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
  159. data/lib/action_view/render/layouts.rb +0 -83
  160. data/lib/action_view/render/rendering.rb +0 -67
  161. data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -3,7 +3,7 @@ require 'uri'
3
3
  require 'set'
4
4
 
5
5
  module ActionController #:nodoc:
6
- # Caching is a cheap way of speeding up slow applications by keeping the result of
6
+ # \Caching is a cheap way of speeding up slow applications by keeping the result of
7
7
  # calculations, renderings, and database calls around for subsequent requests.
8
8
  # Action Controller affords you three approaches in varying levels of granularity:
9
9
  # Page, Action, Fragment.
@@ -14,7 +14,7 @@ module ActionController #:nodoc:
14
14
  # Note: To turn off all caching and sweeping, set
15
15
  # config.action_controller.perform_caching = false.
16
16
  #
17
- # == Caching stores
17
+ # == \Caching stores
18
18
  #
19
19
  # All the caching stores from ActiveSupport::Cache are available to be used as backends
20
20
  # for Action Controller caching. This setting only affects action and fragment caching
@@ -31,8 +31,8 @@ module ActionController #:nodoc:
31
31
  # the subdomain-as-account-key pattern.
32
32
  #
33
33
  # Different representations of the same resource, e.g.
34
- # <tt>http://david.somewhere.com/lists</tt> and
35
- # <tt>http://david.somewhere.com/lists.xml</tt>
34
+ # <tt>http://david.example.com/lists</tt> and
35
+ # <tt>http://david.example.com/lists.xml</tt>
36
36
  # are treated like separate requests and so are cached separately.
37
37
  # Keep in mind when expiring an action cache that
38
38
  # <tt>:action => 'lists'</tt> is not the same as
@@ -56,19 +56,18 @@ module ActionController #:nodoc:
56
56
  #
57
57
  # caches_page :public
58
58
  #
59
- # caches_action :index, :if => proc do |c|
60
- # !c.request.format.json? # cache if is not a JSON request
59
+ # caches_action :index, :if => proc do
60
+ # !request.format.json? # cache if is not a JSON request
61
61
  # end
62
62
  #
63
63
  # caches_action :show, :cache_path => { :project => 1 },
64
64
  # :expires_in => 1.hour
65
65
  #
66
- # caches_action :feed, :cache_path => proc do |c|
67
- # if c.params[:user_id]
68
- # c.send(:user_list_url,
69
- # c.params[:user_id], c.params[:id])
66
+ # caches_action :feed, :cache_path => proc do
67
+ # if params[:user_id]
68
+ # user_list_url(params[:user_id, params[:id])
70
69
  # else
71
- # c.send(:list_url, c.params[:id])
70
+ # list_url(params[:id])
72
71
  # end
73
72
  # end
74
73
  # end
@@ -80,7 +79,7 @@ module ActionController #:nodoc:
80
79
  # header the Content-Type of the cached response could be wrong because
81
80
  # no information about the MIME type is stored in the cache key. So, if
82
81
  # you first ask for MIME type M in the Accept header, a cache entry is
83
- # created, and then perform a second resquest to the same resource asking
82
+ # created, and then perform a second request to the same resource asking
84
83
  # for a different MIME type, you'd get the content cached for M.
85
84
  #
86
85
  # The <tt>:format</tt> parameter is taken into account though. The safest
@@ -160,7 +159,7 @@ module ActionController #:nodoc:
160
159
  attr_reader :path, :extension
161
160
 
162
161
  # If +infer_extension+ is true, the cache path extension is looked up from the request's
163
- # path & format. This is desirable when reading and writing the cache, but not when
162
+ # path and format. This is desirable when reading and writing the cache, but not when
164
163
  # expiring the cache - expire_action should expire the same files regardless of the
165
164
  # request format.
166
165
  def initialize(controller, options = {}, infer_extension = true)
@@ -177,7 +176,7 @@ module ActionController #:nodoc:
177
176
  def normalize!(path)
178
177
  path << 'index' if path[-1] == ?/
179
178
  path << ".#{extension}" if extension and !path.ends_with?(extension)
180
- URI.unescape(path)
179
+ URI.parser.unescape(path)
181
180
  end
182
181
  end
183
182
  end
@@ -1,52 +1,72 @@
1
1
  module ActionController #:nodoc:
2
2
  module Caching
3
- # Fragment caching is used for caching various blocks within templates without caching the entire action as a whole. This is useful when
4
- # certain elements of an action change frequently or depend on complicated state while other parts rarely change or can be shared amongst multiple
5
- # parties. The caching is done using the cache helper available in the Action View. A template with caching might look something like:
3
+ # Fragment caching is used for caching various blocks within
4
+ # views without caching the entire action as a whole. This is
5
+ # useful when certain elements of an action change frequently or
6
+ # depend on complicated state while other parts rarely change or
7
+ # can be shared amongst multiple parties. The caching is done using
8
+ # the <tt>cache</tt> helper available in the Action View. A
9
+ # template with fragment caching might look like:
6
10
  #
7
11
  # <b>Hello <%= @name %></b>
12
+ #
8
13
  # <% cache do %>
9
14
  # All the topics in the system:
10
15
  # <%= render :partial => "topic", :collection => Topic.find(:all) %>
11
16
  # <% end %>
12
17
  #
13
- # This cache will bind to the name of the action that called it, so if this code was part of the view for the topics/list action, you would
14
- # be able to invalidate it using <tt>expire_fragment(:controller => "topics", :action => "list")</tt>.
18
+ # This cache will bind the name of the action that called it, so if
19
+ # this code was part of the view for the topics/list action, you
20
+ # would be able to invalidate it using:
21
+ #
22
+ # expire_fragment(:controller => "topics", :action => "list")
15
23
  #
16
- # This default behavior is of limited use if you need to cache multiple fragments per action or if the action itself is cached using
17
- # <tt>caches_action</tt>, so we also have the option to qualify the name of the cached fragment with something like:
24
+ # This default behavior is limited if you need to cache multiple
25
+ # fragments per action or if the action itself is cached using
26
+ # <tt>caches_action</tt>. To remedy this, there is an option to
27
+ # qualify the name of the cached fragment by using the
28
+ # <tt>:action_suffix</tt> option:
18
29
  #
19
30
  # <% cache(:action => "list", :action_suffix => "all_topics") do %>
20
31
  #
21
- # That would result in a name such as "/topics/list/all_topics", avoiding conflicts with the action cache and with any fragments that use a
22
- # different suffix. Note that the URL doesn't have to really exist or be callable - the url_for system is just used to generate unique
23
- # cache names that we can refer to when we need to expire the cache.
32
+ # That would result in a name such as
33
+ # <tt>/topics/list/all_topics</tt>, avoiding conflicts with the
34
+ # action cache and with any fragments that use a different suffix.
35
+ # Note that the URL doesn't have to really exist or be callable
36
+ # - the url_for system is just used to generate unique cache names
37
+ # that we can refer to when we need to expire the cache.
24
38
  #
25
39
  # The expiration call for this example is:
26
40
  #
27
- # expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics")
41
+ # expire_fragment(:controller => "topics",
42
+ # :action => "list",
43
+ # :action_suffix => "all_topics")
28
44
  module Fragments
29
- # Given a key (as described in <tt>expire_fragment</tt>), returns a key suitable for use in reading,
30
- # writing, or expiring a cached fragment. If the key is a hash, the generated key is the return
31
- # value of url_for on that hash (without the protocol). All keys are prefixed with "views/" and uses
45
+ # Given a key (as described in <tt>expire_fragment</tt>), returns
46
+ # a key suitable for use in reading, writing, or expiring a
47
+ # cached fragment. If the key is a hash, the generated key is the
48
+ # return value of url_for on that hash (without the protocol).
49
+ # All keys are prefixed with <tt>views/</tt> and uses
32
50
  # ActiveSupport::Cache.expand_cache_key for the expansion.
33
51
  def fragment_cache_key(key)
34
52
  ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
35
53
  end
36
54
 
37
- # Writes <tt>content</tt> to the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
55
+ # Writes <tt>content</tt> to the location signified by
56
+ # <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats).
38
57
  def write_fragment(key, content, options = nil)
39
58
  return content unless cache_configured?
40
59
 
41
60
  key = fragment_cache_key(key)
42
61
  instrument_fragment_cache :write_fragment, key do
43
- content = content.html_safe.to_str if content.respond_to?(:html_safe)
62
+ content = content.to_str
44
63
  cache_store.write(key, content, options)
45
64
  end
46
65
  content
47
66
  end
48
67
 
49
- # Reads a cached fragment from the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
68
+ # Reads a cached fragment from the location signified by <tt>key</tt>
69
+ # (see <tt>expire_fragment</tt> for acceptable formats).
50
70
  def read_fragment(key, options = nil)
51
71
  return unless cache_configured?
52
72
 
@@ -57,7 +77,8 @@ module ActionController #:nodoc:
57
77
  end
58
78
  end
59
79
 
60
- # Check if a cached fragment from the location signified by <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
80
+ # Check if a cached fragment from the location signified by
81
+ # <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
61
82
  def fragment_exist?(key, options = nil)
62
83
  return unless cache_configured?
63
84
  key = fragment_cache_key(key)
@@ -70,8 +91,9 @@ module ActionController #:nodoc:
70
91
  # Removes fragments from the cache.
71
92
  #
72
93
  # +key+ can take one of three forms:
94
+ #
73
95
  # * String - This would normally take the form of a path, like
74
- # <tt>"pages/45/notes"</tt>.
96
+ # <tt>pages/45/notes</tt>.
75
97
  # * Hash - Treated as an implicit call to +url_for+, like
76
98
  # <tt>{:controller => "pages", :action => "notes", :id => 45}</tt>
77
99
  # * Regexp - Will remove any fragment that matches, so
@@ -1,5 +1,4 @@
1
1
  require 'fileutils'
2
- require 'uri'
3
2
  require 'active_support/core_ext/class/attribute_accessors'
4
3
 
5
4
  module ActionController #:nodoc:
@@ -99,7 +98,7 @@ module ActionController #:nodoc:
99
98
 
100
99
  private
101
100
  def page_cache_file(path, extension)
102
- name = (path.empty? || path == "/") ? "/index" : URI.unescape(path.chomp('/'))
101
+ name = (path.empty? || path == "/") ? "/index" : URI.parser.unescape(path.chomp('/'))
103
102
  unless (name.split('/').last || name).include? '.'
104
103
  name << (extension || self.page_cache_extension)
105
104
  end
@@ -107,7 +106,7 @@ module ActionController #:nodoc:
107
106
  end
108
107
 
109
108
  def page_cache_path(path, extension = nil)
110
- page_cache_directory + page_cache_file(path, extension)
109
+ page_cache_directory.to_s + page_cache_file(path, extension)
111
110
  end
112
111
 
113
112
  def instrument_page_cache(name, path)
@@ -137,7 +136,7 @@ module ActionController #:nodoc:
137
136
  # If no options are provided, the requested url is used. Example:
138
137
  # cache_page "I'm the cached content", :controller => "lists", :action => "show"
139
138
  def cache_page(content = nil, options = nil)
140
- return unless self.class.perform_caching && caching_allowed
139
+ return unless self.class.perform_caching && caching_allowed?
141
140
 
142
141
  path = case options
143
142
  when Hash
@@ -148,7 +147,6 @@ module ActionController #:nodoc:
148
147
  request.path
149
148
  end
150
149
 
151
-
152
150
  if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
153
151
  extension = ".#{type_symbol}"
154
152
  end
@@ -156,10 +154,6 @@ module ActionController #:nodoc:
156
154
  self.class.cache_page(content || response.body, path, extension)
157
155
  end
158
156
 
159
- private
160
- def caching_allowed
161
- request.get? && response.status.to_i == 200
162
- end
163
157
  end
164
158
  end
165
159
  end
@@ -61,7 +61,6 @@ module ActionController #:nodoc:
61
61
  end
62
62
 
63
63
  def after(controller)
64
- self.controller = controller
65
64
  callback(:after) if controller.perform_caching
66
65
  # Clean up, so that the controller can be collected after this request
67
66
  self.controller = nil
@@ -1,3 +1,3 @@
1
1
  ActionController::AbstractRequest = ActionController::Request = ActionDispatch::Request
2
2
  ActionController::AbstractResponse = ActionController::Response = ActionDispatch::Response
3
- ActionController::Routing = ActionDispatch::Routing
3
+ ActionController::Routing = ActionDispatch::Routing
@@ -46,7 +46,7 @@ module ActionController
46
46
  def #{method}(event)
47
47
  key_or_path = event.payload[:key] || event.payload[:path]
48
48
  human_name = #{method.to_s.humanize.inspect}
49
- info("\#{human_name} \#{key_or_path} (%.1fms)" % event.duration)
49
+ info("\#{human_name} \#{key_or_path} \#{"(%.1fms)" % event.duration}")
50
50
  end
51
51
  METHOD
52
52
  end
@@ -36,35 +36,88 @@ module ActionController
36
36
  action = action.to_s
37
37
  raise "MiddlewareStack#build requires an app" unless app
38
38
 
39
- reverse.inject(app) do |a, middleware|
39
+ middlewares.reverse.inject(app) do |a, middleware|
40
40
  middleware.valid?(action) ?
41
41
  middleware.build(a) : a
42
42
  end
43
43
  end
44
44
  end
45
45
 
46
- # ActionController::Metal provides a way to get a valid Rack application from a controller.
46
+ # <tt>ActionController::Metal</tt> is the simplest possible controller, providing a
47
+ # valid Rack interface without the additional niceties provided by
48
+ # <tt>ActionController::Base</tt>.
49
+ #
50
+ # A sample metal controller might look like this:
51
+ #
52
+ # class HelloController < ActionController::Metal
53
+ # def index
54
+ # self.response_body = "Hello World!"
55
+ # end
56
+ # end
57
+ #
58
+ # And then to route requests to your metal controller, you would add
59
+ # something like this to <tt>config/routes.rb</tt>:
60
+ #
61
+ # match 'hello', :to => HelloController.action(:index)
62
+ #
63
+ # The +action+ method returns a valid Rack application for the \Rails
64
+ # router to dispatch to.
65
+ #
66
+ # == Rendering Helpers
67
+ #
68
+ # <tt>ActionController::Metal</tt> by default provides no utilities for rendering
69
+ # views, partials, or other responses aside from explicitly calling of
70
+ # <tt>response_body=</tt>, <tt>content_type=</tt>, and <tt>status=</tt>. To
71
+ # add the render helpers you're used to having in a normal controller, you
72
+ # can do the following:
73
+ #
74
+ # class HelloController < ActionController::Metal
75
+ # include ActionController::Rendering
76
+ # append_view_path "#{Rails.root}/app/views"
77
+ #
78
+ # def index
79
+ # render "hello/index"
80
+ # end
81
+ # end
82
+ #
83
+ # == Redirection Helpers
84
+ #
85
+ # To add redirection helpers to your metal controller, do the following:
86
+ #
87
+ # class HelloController < ActionController::Metal
88
+ # include ActionController::Redirecting
89
+ # include Rails.application.routes.url_helpers
90
+ #
91
+ # def index
92
+ # redirect_to root_url
93
+ # end
94
+ # end
95
+ #
96
+ # == Other Helpers
97
+ #
98
+ # You can refer to the modules included in <tt>ActionController::Base</tt> to see
99
+ # other features you can bring into your metal controller.
47
100
  #
48
- # In AbstractController, dispatching is triggered directly by calling #process on a new controller.
49
- # ActionController::Metal provides an #action method that returns a valid Rack application for a
50
- # given action. Other rack builders, such as Rack::Builder, Rack::URLMap, and the Rails router,
51
- # can dispatch directly to the action returned by FooController.action(:index).
52
101
  class Metal < AbstractController::Base
53
102
  abstract!
54
103
 
55
- attr_internal :env
104
+ attr_internal_writer :env
105
+
106
+ def env
107
+ @_env ||= {}
108
+ end
56
109
 
57
110
  # Returns the last part of the controller's name, underscored, without the ending
58
- # "Controller". For instance, MyApp::MyPostsController would return "my_posts" for
59
- # controller_name
111
+ # <tt>Controller</tt>. For instance, PostsController returns <tt>posts</tt>.
112
+ # Namespaces are left out, so Admin::PostsController returns <tt>posts</tt> as well.
60
113
  #
61
114
  # ==== Returns
62
- # String
115
+ # * <tt>string</tt>
63
116
  def self.controller_name
64
117
  @controller_name ||= self.name.demodulize.sub(/Controller$/, '').underscore
65
118
  end
66
119
 
67
- # Delegates to the class' #controller_name
120
+ # Delegates to the class' <tt>controller_name</tt>
68
121
  def controller_name
69
122
  self.class.controller_name
70
123
  end
@@ -78,9 +131,12 @@ module ActionController
78
131
  attr_internal :headers, :response, :request
79
132
  delegate :session, :to => "@_request"
80
133
 
81
- def initialize(*)
134
+ def initialize
82
135
  @_headers = {"Content-Type" => "text/html"}
83
136
  @_status = 200
137
+ @_request = nil
138
+ @_response = nil
139
+ @_routes = nil
84
140
  super
85
141
  end
86
142
 
@@ -126,12 +182,11 @@ module ActionController
126
182
  end
127
183
 
128
184
  def response_body=(val)
129
- body = val.respond_to?(:each) ? val : [val]
185
+ body = val.nil? ? nil : (val.respond_to?(:each) ? val : [val])
130
186
  super body
131
187
  end
132
188
 
133
- # :api: private
134
- def dispatch(name, request)
189
+ def dispatch(name, request) #:nodoc:
135
190
  @_request = request
136
191
  @_env = request.env
137
192
  @_env['action_controller.instance'] = self
@@ -139,27 +194,30 @@ module ActionController
139
194
  to_a
140
195
  end
141
196
 
142
- # :api: private
143
- def to_a
197
+ def to_a #:nodoc:
144
198
  response ? response.to_a : [status, headers, response_body]
145
199
  end
146
200
 
147
201
  class_attribute :middleware_stack
148
202
  self.middleware_stack = ActionController::MiddlewareStack.new
149
203
 
150
- def self.inherited(base)
204
+ def self.inherited(base) #nodoc:
151
205
  base.middleware_stack = self.middleware_stack.dup
152
206
  super
153
207
  end
154
208
 
209
+ # Adds given middleware class and its args to bottom of middleware_stack
155
210
  def self.use(*args, &block)
156
211
  middleware_stack.use(*args, &block)
157
212
  end
158
213
 
214
+ # Alias for middleware_stack
159
215
  def self.middleware
160
216
  middleware_stack
161
217
  end
162
218
 
219
+ # Makes the controller a rack endpoint that points to the action in
220
+ # the given env's action_dispatch.request.path_parameters key.
163
221
  def self.call(env)
164
222
  action(env['action_dispatch.request.path_parameters'][:action]).call(env)
165
223
  end
@@ -169,10 +227,10 @@ module ActionController
169
227
  # for the same action.
170
228
  #
171
229
  # ==== Parameters
172
- # action<#to_s>:: An action name
230
+ # * <tt>action</tt> - An action name
173
231
  #
174
232
  # ==== Returns
175
- # Proc:: A rack application
233
+ # * <tt>proc</tt> - A rack application
176
234
  def self.action(name, klass = ActionDispatch::Request)
177
235
  middleware_stack.build(name.to_s) do |env|
178
236
  new.dispatch(name, klass.new(env))
@@ -5,9 +5,6 @@ module ActionController
5
5
  class ::ActionController::ActionControllerError < StandardError #:nodoc:
6
6
  end
7
7
 
8
- module ClassMethods
9
- end
10
-
11
8
  # Temporary hax
12
9
  included do
13
10
  ::ActionController::UnknownAction = ::AbstractController::ActionNotFound
@@ -39,12 +36,6 @@ module ActionController
39
36
  def assign_shortcuts(*) end
40
37
 
41
38
  def _normalize_options(options)
42
- if options[:action] && options[:action].to_s.include?(?/)
43
- ActiveSupport::Deprecation.warn "Giving a path to render :action is deprecated. " <<
44
- "Please use render :template instead", caller
45
- options[:template] = options.delete(:action)
46
- end
47
-
48
39
  options[:text] = nil if options.delete(:nothing) == true
49
40
  options[:text] = " " if options.key?(:text) && options[:text].nil?
50
41
  super