actionpack 3.2.22.5 → 4.0.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 (265) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +641 -418
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -288
  5. data/lib/abstract_controller.rb +1 -8
  6. data/lib/abstract_controller/asset_paths.rb +2 -2
  7. data/lib/abstract_controller/base.rb +39 -37
  8. data/lib/abstract_controller/callbacks.rb +101 -82
  9. data/lib/abstract_controller/collector.rb +7 -3
  10. data/lib/abstract_controller/helpers.rb +23 -11
  11. data/lib/abstract_controller/layouts.rb +68 -73
  12. data/lib/abstract_controller/logger.rb +1 -2
  13. data/lib/abstract_controller/rendering.rb +22 -13
  14. data/lib/abstract_controller/translation.rb +16 -1
  15. data/lib/abstract_controller/url_for.rb +6 -6
  16. data/lib/abstract_controller/view_paths.rb +1 -1
  17. data/lib/action_controller.rb +15 -6
  18. data/lib/action_controller/base.rb +46 -22
  19. data/lib/action_controller/caching.rb +46 -33
  20. data/lib/action_controller/caching/fragments.rb +23 -53
  21. data/lib/action_controller/deprecated.rb +5 -1
  22. data/lib/action_controller/deprecated/integration_test.rb +3 -0
  23. data/lib/action_controller/log_subscriber.rb +11 -8
  24. data/lib/action_controller/metal.rb +16 -30
  25. data/lib/action_controller/metal/conditional_get.rb +76 -32
  26. data/lib/action_controller/metal/data_streaming.rb +20 -26
  27. data/lib/action_controller/metal/exceptions.rb +19 -6
  28. data/lib/action_controller/metal/flash.rb +24 -9
  29. data/lib/action_controller/metal/force_ssl.rb +32 -9
  30. data/lib/action_controller/metal/head.rb +25 -4
  31. data/lib/action_controller/metal/helpers.rb +6 -9
  32. data/lib/action_controller/metal/hide_actions.rb +1 -2
  33. data/lib/action_controller/metal/http_authentication.rb +105 -87
  34. data/lib/action_controller/metal/implicit_render.rb +1 -1
  35. data/lib/action_controller/metal/instrumentation.rb +2 -1
  36. data/lib/action_controller/metal/live.rb +141 -0
  37. data/lib/action_controller/metal/mime_responds.rb +161 -47
  38. data/lib/action_controller/metal/params_wrapper.rb +112 -74
  39. data/lib/action_controller/metal/rack_delegation.rb +9 -3
  40. data/lib/action_controller/metal/redirecting.rb +15 -20
  41. data/lib/action_controller/metal/renderers.rb +11 -9
  42. data/lib/action_controller/metal/rendering.rb +8 -0
  43. data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
  44. data/lib/action_controller/metal/responder.rb +20 -19
  45. data/lib/action_controller/metal/streaming.rb +12 -18
  46. data/lib/action_controller/metal/strong_parameters.rb +516 -0
  47. data/lib/action_controller/metal/testing.rb +13 -18
  48. data/lib/action_controller/metal/url_for.rb +27 -25
  49. data/lib/action_controller/model_naming.rb +12 -0
  50. data/lib/action_controller/railtie.rb +33 -17
  51. data/lib/action_controller/railties/helpers.rb +22 -0
  52. data/lib/action_controller/record_identifier.rb +18 -72
  53. data/lib/action_controller/test_case.rb +215 -123
  54. data/lib/action_controller/vendor/html-scanner.rb +4 -19
  55. data/lib/action_dispatch.rb +27 -19
  56. data/lib/action_dispatch/http/cache.rb +63 -11
  57. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  58. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  59. data/lib/action_dispatch/http/headers.rb +27 -19
  60. data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
  61. data/lib/action_dispatch/http/mime_type.rb +145 -113
  62. data/lib/action_dispatch/http/mime_types.rb +1 -1
  63. data/lib/action_dispatch/http/parameter_filter.rb +44 -46
  64. data/lib/action_dispatch/http/parameters.rb +12 -5
  65. data/lib/action_dispatch/http/rack_cache.rb +2 -3
  66. data/lib/action_dispatch/http/request.rb +49 -18
  67. data/lib/action_dispatch/http/response.rb +129 -35
  68. data/lib/action_dispatch/http/upload.rb +60 -17
  69. data/lib/action_dispatch/http/url.rb +53 -31
  70. data/lib/action_dispatch/journey.rb +5 -0
  71. data/lib/action_dispatch/journey/backwards.rb +5 -0
  72. data/lib/action_dispatch/journey/formatter.rb +146 -0
  73. data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
  74. data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
  75. data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
  76. data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
  77. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  78. data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
  79. data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
  80. data/lib/action_dispatch/journey/nodes/node.rb +124 -0
  81. data/lib/action_dispatch/journey/parser.rb +206 -0
  82. data/lib/action_dispatch/journey/parser.y +47 -0
  83. data/lib/action_dispatch/journey/parser_extras.rb +23 -0
  84. data/lib/action_dispatch/journey/path/pattern.rb +196 -0
  85. data/lib/action_dispatch/journey/route.rb +116 -0
  86. data/lib/action_dispatch/journey/router.rb +164 -0
  87. data/lib/action_dispatch/journey/router/strexp.rb +24 -0
  88. data/lib/action_dispatch/journey/router/utils.rb +54 -0
  89. data/lib/action_dispatch/journey/routes.rb +75 -0
  90. data/lib/action_dispatch/journey/scanner.rb +61 -0
  91. data/lib/action_dispatch/journey/visitors.rb +189 -0
  92. data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
  93. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  94. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  95. data/lib/action_dispatch/middleware/callbacks.rb +9 -4
  96. data/lib/action_dispatch/middleware/cookies.rb +168 -57
  97. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
  98. data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
  99. data/lib/action_dispatch/middleware/flash.rb +58 -58
  100. data/lib/action_dispatch/middleware/params_parser.rb +14 -29
  101. data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
  102. data/lib/action_dispatch/middleware/reloader.rb +6 -6
  103. data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
  104. data/lib/action_dispatch/middleware/request_id.rb +2 -6
  105. data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
  106. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  107. data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
  108. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
  109. data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
  110. data/lib/action_dispatch/middleware/ssl.rb +70 -0
  111. data/lib/action_dispatch/middleware/stack.rb +6 -1
  112. data/lib/action_dispatch/middleware/static.rb +5 -24
  113. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
  114. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
  115. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
  116. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
  117. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
  122. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  123. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
  124. data/lib/action_dispatch/railtie.rb +16 -6
  125. data/lib/action_dispatch/request/session.rb +181 -0
  126. data/lib/action_dispatch/routing.rb +41 -40
  127. data/lib/action_dispatch/routing/inspector.rb +240 -0
  128. data/lib/action_dispatch/routing/mapper.rb +501 -273
  129. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
  130. data/lib/action_dispatch/routing/redirection.rb +46 -29
  131. data/lib/action_dispatch/routing/route_set.rb +203 -164
  132. data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
  133. data/lib/action_dispatch/routing/url_for.rb +48 -33
  134. data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
  135. data/lib/action_dispatch/testing/assertions/response.rb +32 -40
  136. data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
  137. data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
  138. data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
  139. data/lib/action_dispatch/testing/integration.rb +41 -22
  140. data/lib/action_dispatch/testing/test_process.rb +9 -6
  141. data/lib/action_dispatch/testing/test_request.rb +7 -3
  142. data/lib/action_pack.rb +1 -1
  143. data/lib/action_pack/version.rb +4 -4
  144. data/lib/action_view.rb +17 -8
  145. data/lib/action_view/base.rb +15 -34
  146. data/lib/action_view/buffers.rb +1 -1
  147. data/lib/action_view/context.rb +4 -4
  148. data/lib/action_view/dependency_tracker.rb +91 -0
  149. data/lib/action_view/digestor.rb +85 -0
  150. data/lib/action_view/flows.rb +1 -4
  151. data/lib/action_view/helpers.rb +2 -4
  152. data/lib/action_view/helpers/active_model_helper.rb +3 -4
  153. data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
  154. data/lib/action_view/helpers/asset_url_helper.rb +354 -0
  155. data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
  156. data/lib/action_view/helpers/cache_helper.rb +150 -18
  157. data/lib/action_view/helpers/capture_helper.rb +42 -29
  158. data/lib/action_view/helpers/csrf_helper.rb +0 -2
  159. data/lib/action_view/helpers/date_helper.rb +268 -247
  160. data/lib/action_view/helpers/debug_helper.rb +10 -11
  161. data/lib/action_view/helpers/form_helper.rb +904 -547
  162. data/lib/action_view/helpers/form_options_helper.rb +341 -166
  163. data/lib/action_view/helpers/form_tag_helper.rb +188 -88
  164. data/lib/action_view/helpers/javascript_helper.rb +23 -16
  165. data/lib/action_view/helpers/number_helper.rb +148 -354
  166. data/lib/action_view/helpers/output_safety_helper.rb +3 -3
  167. data/lib/action_view/helpers/record_tag_helper.rb +17 -22
  168. data/lib/action_view/helpers/rendering_helper.rb +2 -4
  169. data/lib/action_view/helpers/sanitize_helper.rb +3 -6
  170. data/lib/action_view/helpers/tag_helper.rb +43 -37
  171. data/lib/action_view/helpers/tags.rb +39 -0
  172. data/lib/action_view/helpers/tags/base.rb +148 -0
  173. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  174. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  175. data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
  176. data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
  177. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  178. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  179. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  180. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  181. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  182. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  183. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  184. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  185. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  186. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  187. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  188. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  189. data/lib/action_view/helpers/tags/label.rb +65 -0
  190. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  191. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  192. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  193. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  194. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  195. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  196. data/lib/action_view/helpers/tags/select.rb +41 -0
  197. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  198. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  199. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  200. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  201. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  202. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  203. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  204. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  205. data/lib/action_view/helpers/text_helper.rb +126 -113
  206. data/lib/action_view/helpers/translation_helper.rb +32 -16
  207. data/lib/action_view/helpers/url_helper.rb +200 -271
  208. data/lib/action_view/locale/en.yml +1 -105
  209. data/lib/action_view/log_subscriber.rb +6 -4
  210. data/lib/action_view/lookup_context.rb +15 -39
  211. data/lib/action_view/model_naming.rb +12 -0
  212. data/lib/action_view/path_set.rb +9 -39
  213. data/lib/action_view/railtie.rb +6 -22
  214. data/lib/action_view/record_identifier.rb +84 -0
  215. data/lib/action_view/renderer/abstract_renderer.rb +10 -19
  216. data/lib/action_view/renderer/partial_renderer.rb +144 -81
  217. data/lib/action_view/renderer/renderer.rb +2 -19
  218. data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
  219. data/lib/action_view/renderer/template_renderer.rb +14 -13
  220. data/lib/action_view/routing_url_for.rb +107 -0
  221. data/lib/action_view/template.rb +22 -21
  222. data/lib/action_view/template/error.rb +22 -12
  223. data/lib/action_view/template/handlers.rb +12 -9
  224. data/lib/action_view/template/handlers/builder.rb +1 -1
  225. data/lib/action_view/template/handlers/erb.rb +11 -16
  226. data/lib/action_view/template/handlers/raw.rb +11 -0
  227. data/lib/action_view/template/resolver.rb +111 -83
  228. data/lib/action_view/template/text.rb +12 -8
  229. data/lib/action_view/template/types.rb +57 -0
  230. data/lib/action_view/test_case.rb +66 -43
  231. data/lib/action_view/testing/resolvers.rb +3 -2
  232. data/lib/action_view/vendor/html-scanner.rb +20 -0
  233. data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
  234. data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
  235. data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
  236. data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
  237. data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
  238. data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
  239. metadata +135 -125
  240. data/lib/action_controller/caching/actions.rb +0 -185
  241. data/lib/action_controller/caching/pages.rb +0 -187
  242. data/lib/action_controller/caching/sweeping.rb +0 -97
  243. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  244. data/lib/action_controller/metal/compatibility.rb +0 -65
  245. data/lib/action_controller/metal/session_management.rb +0 -14
  246. data/lib/action_controller/railties/paths.rb +0 -25
  247. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  248. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  249. data/lib/action_dispatch/middleware/head.rb +0 -18
  250. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  251. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  252. data/lib/action_view/asset_paths.rb +0 -142
  253. data/lib/action_view/helpers/asset_paths.rb +0 -7
  254. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  255. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  256. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  257. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  258. data/lib/sprockets/assets.rake +0 -99
  259. data/lib/sprockets/bootstrap.rb +0 -37
  260. data/lib/sprockets/compressors.rb +0 -83
  261. data/lib/sprockets/helpers.rb +0 -6
  262. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  263. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  264. data/lib/sprockets/railtie.rb +0 -62
  265. data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,59 +1,29 @@
1
- module ActionController #:nodoc:
1
+ module ActionController
2
2
  module Caching
3
- # Fragment caching is used for caching various blocks within
3
+ # Fragment caching is used for caching various blocks within
4
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
5
+ # useful when certain elements of an action change frequently or
6
+ # depend on complicated state while other parts rarely change or
7
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:
8
+ # the +cache+ helper available in the Action View. See
9
+ # ActionView::Helpers::CacheHelper for more information.
10
10
  #
11
- # <b>Hello <%= @name %></b>
11
+ # While it's strongly recommended that you use key-based cache
12
+ # expiration (see links in CacheHelper for more information),
13
+ # it is also possible to manually expire caches. For example:
12
14
  #
13
- # <% cache do %>
14
- # All the topics in the system:
15
- # <%= render :partial => "topic", :collection => Topic.all %>
16
- # <% end %>
17
- #
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")
23
- #
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:
29
- #
30
- # <% cache(:action => "list", :action_suffix => "all_topics") do %>
31
- #
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.
38
- #
39
- # The expiration call for this example is:
40
- #
41
- # expire_fragment(:controller => "topics",
42
- # :action => "list",
43
- # :action_suffix => "all_topics")
15
+ # expire_fragment('name_of_cache')
44
16
  module Fragments
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
17
+ # Given a key (as described in +expire_fragment+), returns
18
+ # a key suitable for use in reading, writing, or expiring a
19
+ # cached fragment. All keys are prefixed with <tt>views/</tt> and uses
50
20
  # ActiveSupport::Cache.expand_cache_key for the expansion.
51
21
  def fragment_cache_key(key)
52
22
  ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
53
23
  end
54
24
 
55
- # Writes <tt>content</tt> to the location signified by
56
- # <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats).
25
+ # Writes +content+ to the location signified by
26
+ # +key+ (see +expire_fragment+ for acceptable formats).
57
27
  def write_fragment(key, content, options = nil)
58
28
  return content unless cache_configured?
59
29
 
@@ -65,8 +35,8 @@ module ActionController #:nodoc:
65
35
  content
66
36
  end
67
37
 
68
- # Reads a cached fragment from the location signified by <tt>key</tt>
69
- # (see <tt>expire_fragment</tt> for acceptable formats).
38
+ # Reads a cached fragment from the location signified by +key+
39
+ # (see +expire_fragment+ for acceptable formats).
70
40
  def read_fragment(key, options = nil)
71
41
  return unless cache_configured?
72
42
 
@@ -77,8 +47,8 @@ module ActionController #:nodoc:
77
47
  end
78
48
  end
79
49
 
80
- # Check if a cached fragment from the location signified by
81
- # <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
50
+ # Check if a cached fragment from the location signified by
51
+ # +key+ exists (see +expire_fragment+ for acceptable formats).
82
52
  def fragment_exist?(key, options = nil)
83
53
  return unless cache_configured?
84
54
  key = fragment_cache_key(key)
@@ -95,7 +65,7 @@ module ActionController #:nodoc:
95
65
  # * String - This would normally take the form of a path, like
96
66
  # <tt>pages/45/notes</tt>.
97
67
  # * Hash - Treated as an implicit call to +url_for+, like
98
- # <tt>{:controller => "pages", :action => "notes", :id => 45}</tt>
68
+ # <tt>{ controller: 'pages', action: 'notes', id: 45}</tt>
99
69
  # * Regexp - Will remove any fragment that matches, so
100
70
  # <tt>%r{pages/\d*/notes}</tt> might remove all notes. Make sure you
101
71
  # don't use anchors in the regex (<tt>^</tt> or <tt>$</tt>) because
@@ -104,8 +74,8 @@ module ActionController #:nodoc:
104
74
  # only supported on caches that can iterate over all keys (unlike
105
75
  # memcached).
106
76
  #
107
- # +options+ is passed through to the cache store's <tt>delete</tt>
108
- # method (or <tt>delete_matched</tt>, for Regexp keys.)
77
+ # +options+ is passed through to the cache store's +delete+
78
+ # method (or <tt>delete_matched</tt>, for Regexp keys).
109
79
  def expire_fragment(key, options = nil)
110
80
  return unless cache_configured?
111
81
  key = fragment_cache_key(key) unless key.is_a?(Regexp)
@@ -119,7 +89,7 @@ module ActionController #:nodoc:
119
89
  end
120
90
  end
121
91
 
122
- def instrument_fragment_cache(name, key)
92
+ def instrument_fragment_cache(name, key) # :nodoc:
123
93
  ActiveSupport::Notifications.instrument("#{name}.action_controller", :key => key){ yield }
124
94
  end
125
95
  end
@@ -1,3 +1,7 @@
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
4
+
5
+ ActiveSupport::Deprecation.warn 'ActionController::AbstractRequest and ActionController::Request are deprecated and will be removed, use ActionDispatch::Request instead.'
6
+ ActiveSupport::Deprecation.warn 'ActionController::AbstractResponse and ActionController::Response are deprecated and will be removed, use ActionDispatch::Response instead.'
7
+ ActiveSupport::Deprecation.warn 'ActionController::Routing is deprecated and will be removed, use ActionDispatch::Routing instead.'
@@ -1,2 +1,5 @@
1
1
  ActionController::Integration = ActionDispatch::Integration
2
2
  ActionController::IntegrationTest = ActionDispatch::IntegrationTest
3
+
4
+ ActiveSupport::Deprecation.warn 'ActionController::Integration is deprecated and will be removed, use ActionDispatch::Integration instead.'
5
+ ActiveSupport::Deprecation.warn 'ActionController::IntegrationTest is deprecated and will be removed, use ActionDispatch::IntegrationTest instead.'
@@ -1,10 +1,11 @@
1
- require 'active_support/core_ext/object/blank'
2
1
 
3
2
  module ActionController
4
3
  class LogSubscriber < ActiveSupport::LogSubscriber
5
4
  INTERNAL_PARAMS = %w(controller action format _method only_path)
6
5
 
7
6
  def start_processing(event)
7
+ return unless logger.info?
8
+
8
9
  payload = event.payload
9
10
  params = payload[:params].except(*INTERNAL_PARAMS)
10
11
  format = payload[:format]
@@ -15,6 +16,8 @@ module ActionController
15
16
  end
16
17
 
17
18
  def process_action(event)
19
+ return unless logger.info?
20
+
18
21
  payload = event.payload
19
22
  additions = ActionController::Base.log_process_action(payload)
20
23
 
@@ -23,36 +26,36 @@ module ActionController
23
26
  exception_class_name = payload[:exception].first
24
27
  status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
25
28
  end
26
- message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{format_duration(event.duration)}"
29
+ message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
27
30
  message << " (#{additions.join(" | ")})" unless additions.blank?
28
31
 
29
32
  info(message)
30
33
  end
31
34
 
32
35
  def halted_callback(event)
33
- info "Filter chain halted as #{event.payload[:filter]} rendered or redirected"
36
+ info("Filter chain halted as #{event.payload[:filter]} rendered or redirected")
34
37
  end
35
38
 
36
39
  def send_file(event)
37
- info("Sent file #{event.payload[:path]} (#{format_duration(event.duration)})")
40
+ info("Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)")
38
41
  end
39
42
 
40
43
  def redirect_to(event)
41
- info "Redirected to #{event.payload[:location]}"
44
+ info("Redirected to #{event.payload[:location]}")
42
45
  end
43
46
 
44
47
  def send_data(event)
45
- info("Sent data #{event.payload[:filename]} (#{format_duration(event.duration)})")
48
+ info("Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)")
46
49
  end
47
50
 
48
51
  %w(write_fragment read_fragment exist_fragment?
49
52
  expire_fragment expire_page write_page).each do |method|
50
53
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
51
54
  def #{method}(event)
55
+ return unless logger.info?
52
56
  key_or_path = event.payload[:key] || event.payload[:path]
53
57
  human_name = #{method.to_s.humanize.inspect}
54
- duration = format_duration(event.duration)
55
- info("\#{human_name} \#{key_or_path} \#{duration}")
58
+ info("\#{human_name} \#{key_or_path} (\#{event.duration.round(1)}ms)")
56
59
  end
57
60
  METHOD
58
61
  end
@@ -1,5 +1,4 @@
1
- require 'active_support/core_ext/class/attribute'
2
- require 'active_support/core_ext/object/blank'
1
+ require 'active_support/core_ext/array/extract_options'
3
2
  require 'action_dispatch/middleware/stack'
4
3
 
5
4
  module ActionController
@@ -7,7 +6,7 @@ module ActionController
7
6
  # allowing the following syntax in controllers:
8
7
  #
9
8
  # class PostsController < ApplicationController
10
- # use AuthenticationMiddleware, :except => [:index, :show]
9
+ # use AuthenticationMiddleware, except: [:index, :show]
11
10
  # end
12
11
  #
13
12
  class MiddlewareStack < ActionDispatch::MiddlewareStack #:nodoc:
@@ -58,7 +57,7 @@ module ActionController
58
57
  # And then to route requests to your metal controller, you would add
59
58
  # something like this to <tt>config/routes.rb</tt>:
60
59
  #
61
- # match 'hello', :to => HelloController.action(:index)
60
+ # match 'hello', to: HelloController.action(:index)
62
61
  #
63
62
  # The +action+ method returns a valid Rack application for the \Rails
64
63
  # router to dispatch to.
@@ -114,7 +113,7 @@ module ActionController
114
113
  # ==== Returns
115
114
  # * <tt>string</tt>
116
115
  def self.controller_name
117
- @controller_name ||= self.name.demodulize.sub(/Controller$/, '').underscore
116
+ @controller_name ||= name.demodulize.sub(/Controller$/, '').underscore
118
117
  end
119
118
 
120
119
  # Delegates to the class' <tt>controller_name</tt>
@@ -181,19 +180,13 @@ module ActionController
181
180
  @_status = Rack::Utils.status_code(status)
182
181
  end
183
182
 
184
- def response_body=(val)
185
- body = if val.is_a?(String)
186
- [val]
187
- elsif val.nil? || val.respond_to?(:each)
188
- val
189
- else
190
- [val]
191
- end
192
- super body
183
+ def response_body=(body)
184
+ body = [body] unless body.nil? || body.respond_to?(:each)
185
+ super
193
186
  end
194
187
 
195
188
  def performed?
196
- response_body
189
+ response_body || (response && response.committed?)
197
190
  end
198
191
 
199
192
  def dispatch(name, request) #:nodoc:
@@ -211,36 +204,29 @@ module ActionController
211
204
  class_attribute :middleware_stack
212
205
  self.middleware_stack = ActionController::MiddlewareStack.new
213
206
 
214
- def self.inherited(base) #nodoc:
215
- base.middleware_stack = self.middleware_stack.dup
207
+ def self.inherited(base) # :nodoc:
208
+ base.middleware_stack = middleware_stack.dup
216
209
  super
217
210
  end
218
211
 
219
- # Adds given middleware class and its args to bottom of middleware_stack
212
+ # Pushes the given Rack middleware and its arguments to the bottom of the
213
+ # middleware stack.
220
214
  def self.use(*args, &block)
221
215
  middleware_stack.use(*args, &block)
222
216
  end
223
217
 
224
- # Alias for middleware_stack
218
+ # Alias for +middleware_stack+.
225
219
  def self.middleware
226
220
  middleware_stack
227
221
  end
228
222
 
229
- # Makes the controller a rack endpoint that points to the action in
230
- # the given env's action_dispatch.request.path_parameters key.
223
+ # Makes the controller a Rack endpoint that runs the action in the given
224
+ # +env+'s +action_dispatch.request.path_parameters+ key.
231
225
  def self.call(env)
232
226
  action(env['action_dispatch.request.path_parameters'][:action]).call(env)
233
227
  end
234
228
 
235
- # Return a rack endpoint for the given action. Memoize the endpoint, so
236
- # multiple calls into MyController.action will return the same object
237
- # for the same action.
238
- #
239
- # ==== Parameters
240
- # * <tt>action</tt> - An action name
241
- #
242
- # ==== Returns
243
- # * <tt>proc</tt> - A rack application
229
+ # Returns a Rack endpoint for the given action name.
244
230
  def self.action(name, klass = ActionDispatch::Request)
245
231
  middleware_stack.build(name.to_s) do |env|
246
232
  new.dispatch(name, klass.new(env))
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/hash/keys'
2
+
1
3
  module ActionController
2
4
  module ConditionalGet
3
5
  extend ActiveSupport::Concern
@@ -5,25 +7,53 @@ module ActionController
5
7
  include RackDelegation
6
8
  include Head
7
9
 
8
- # Sets the etag, last_modified, or both on the response and renders a
10
+ included do
11
+ class_attribute :etaggers
12
+ self.etaggers = []
13
+ end
14
+
15
+ module ClassMethods
16
+ # Allows you to consider additional controller-wide information when generating an etag.
17
+ # For example, if you serve pages tailored depending on who's logged in at the moment, you
18
+ # may want to add the current user id to be part of the etag to prevent authorized displaying
19
+ # of cached pages.
20
+ #
21
+ # class InvoicesController < ApplicationController
22
+ # etag { current_user.try :id }
23
+ #
24
+ # def show
25
+ # # Etag will differ even for the same invoice when it's viewed by a different current_user
26
+ # @invoice = Invoice.find(params[:id])
27
+ # fresh_when(@invoice)
28
+ # end
29
+ # end
30
+ def etag(&etagger)
31
+ self.etaggers += [etagger]
32
+ end
33
+ end
34
+
35
+ # Sets the etag, +last_modified+, or both on the response and renders a
9
36
  # <tt>304 Not Modified</tt> response if the request is already fresh.
10
37
  #
11
- # Parameters:
12
- # * <tt>:etag</tt>
13
- # * <tt>:last_modified</tt>
14
- # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
38
+ # === Parameters:
15
39
  #
16
- # Example:
40
+ # * <tt>:etag</tt>.
41
+ # * <tt>:last_modified</tt>.
42
+ # * <tt>:public</tt> By default the Cache-Control header is private, set this to
43
+ # +true+ if you want your application to be cachable by other devices (proxy caches).
44
+ #
45
+ # === Example:
17
46
  #
18
47
  # def show
19
48
  # @article = Article.find(params[:id])
20
- # fresh_when(:etag => @article, :last_modified => @article.created_at, :public => true)
49
+ # fresh_when(etag: @article, last_modified: @article.created_at, public: true)
21
50
  # end
22
51
  #
23
52
  # This will render the show template if the request isn't sending a matching etag or
24
53
  # If-Modified-Since header and just a <tt>304 Not Modified</tt> response if there's a match.
25
54
  #
26
- # You can also just pass a record where last_modified will be set by calling updated_at and the etag by passing the object itself. Example:
55
+ # You can also just pass a record where +last_modified+ will be set by calling
56
+ # +updated_at+ and the etag by passing the object itself.
27
57
  #
28
58
  # def show
29
59
  # @article = Article.find(params[:id])
@@ -34,7 +64,7 @@ module ActionController
34
64
  #
35
65
  # def show
36
66
  # @article = Article.find(params[:id])
37
- # fresh_when(@article, :public => true)
67
+ # fresh_when(@article, public: true)
38
68
  # end
39
69
  def fresh_when(record_or_options, additional_options = {})
40
70
  if record_or_options.is_a? Hash
@@ -42,32 +72,34 @@ module ActionController
42
72
  options.assert_valid_keys(:etag, :last_modified, :public)
43
73
  else
44
74
  record = record_or_options
45
- options = { :etag => record, :last_modified => record.try(:updated_at) }.merge(additional_options)
75
+ options = { etag: record, last_modified: record.try(:updated_at) }.merge!(additional_options)
46
76
  end
47
77
 
48
- response.etag = options[:etag] if options[:etag]
49
- response.last_modified = options[:last_modified] if options[:last_modified]
50
- response.cache_control[:public] = true if options[:public]
78
+ response.etag = combine_etags(options[:etag]) if options[:etag]
79
+ response.last_modified = options[:last_modified] if options[:last_modified]
80
+ response.cache_control[:public] = true if options[:public]
51
81
 
52
82
  head :not_modified if request.fresh?(response)
53
83
  end
54
84
 
55
- # Sets the etag and/or last_modified on the response and checks it against
85
+ # Sets the +etag+ and/or +last_modified+ on the response and checks it against
56
86
  # the client request. If the request doesn't match the options provided, the
57
87
  # request is considered stale and should be generated from scratch. Otherwise,
58
88
  # it's fresh and we don't need to generate anything and a reply of <tt>304 Not Modified</tt> is sent.
59
89
  #
60
- # Parameters:
61
- # * <tt>:etag</tt>
62
- # * <tt>:last_modified</tt>
63
- # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
90
+ # === Parameters:
91
+ #
92
+ # * <tt>:etag</tt>.
93
+ # * <tt>:last_modified</tt>.
94
+ # * <tt>:public</tt> By default the Cache-Control header is private, set this to
95
+ # +true+ if you want your application to be cachable by other devices (proxy caches).
64
96
  #
65
- # Example:
97
+ # === Example:
66
98
  #
67
99
  # def show
68
100
  # @article = Article.find(params[:id])
69
101
  #
70
- # if stale?(:etag => @article, :last_modified => @article.created_at)
102
+ # if stale?(etag: @article, last_modified: @article.created_at)
71
103
  # @statistics = @article.really_expensive_call
72
104
  # respond_to do |format|
73
105
  # # all the supported formats
@@ -75,7 +107,8 @@ module ActionController
75
107
  # end
76
108
  # end
77
109
  #
78
- # You can also just pass a record where last_modified will be set by calling updated_at and the etag by passing the object itself. Example:
110
+ # You can also just pass a record where +last_modified+ will be set by calling
111
+ # updated_at and the etag by passing the object itself.
79
112
  #
80
113
  # def show
81
114
  # @article = Article.find(params[:id])
@@ -93,7 +126,7 @@ module ActionController
93
126
  # def show
94
127
  # @article = Article.find(params[:id])
95
128
  #
96
- # if stale?(@article, :public => true)
129
+ # if stale?(@article, public: true)
97
130
  # @statistics = @article.really_expensive_call
98
131
  # respond_to do |format|
99
132
  # # all the supported formats
@@ -105,27 +138,38 @@ module ActionController
105
138
  !request.fresh?(response)
106
139
  end
107
140
 
108
- # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a <tt>private</tt> instruction, so that
109
- # intermediate caches must not cache the response.
141
+ # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a +private+
142
+ # instruction, so that intermediate caches must not cache the response.
110
143
  #
111
- # Examples:
112
144
  # expires_in 20.minutes
113
- # expires_in 3.hours, :public => true
114
- # expires_in 3.hours, 'max-stale' => 5.hours, :public => true
145
+ # expires_in 3.hours, public: true
146
+ # expires_in 3.hours, public: true, must_revalidate: true
115
147
  #
116
148
  # This method will overwrite an existing Cache-Control header.
117
149
  # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
118
- def expires_in(seconds, options = {}) #:doc:
119
- response.cache_control.merge!(:max_age => seconds, :public => options.delete(:public))
150
+ #
151
+ # The method will also ensure a HTTP Date header for client compatibility.
152
+ def expires_in(seconds, options = {})
153
+ response.cache_control.merge!(
154
+ :max_age => seconds,
155
+ :public => options.delete(:public),
156
+ :must_revalidate => options.delete(:must_revalidate)
157
+ )
120
158
  options.delete(:private)
121
159
 
122
160
  response.cache_control[:extras] = options.map {|k,v| "#{k}=#{v}"}
161
+ response.date = Time.now unless response.date?
123
162
  end
124
163
 
125
- # Sets a HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should occur by the browser or
126
- # intermediate caches (like caching proxy servers).
127
- def expires_now #:doc:
164
+ # Sets a HTTP 1.1 Cache-Control header of <tt>no-cache</tt> so no caching should
165
+ # occur by the browser or intermediate caches (like caching proxy servers).
166
+ def expires_now
128
167
  response.cache_control.replace(:no_cache => true)
129
168
  end
169
+
170
+ private
171
+ def combine_etags(etag)
172
+ [ etag, *etaggers.map { |etagger| instance_exec(&etagger) }.compact ]
173
+ end
130
174
  end
131
175
  end