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,185 +0,0 @@
1
- require 'set'
2
-
3
- module ActionController #:nodoc:
4
- module Caching
5
- # Action caching is similar to page caching by the fact that the entire
6
- # output of the response is cached, but unlike page caching, every
7
- # request still goes through Action Pack. The key benefit of this is
8
- # that filters run before the cache is served, which allows for
9
- # authentication and other restrictions on whether someone is allowed
10
- # to execute such action. Example:
11
- #
12
- # class ListsController < ApplicationController
13
- # before_filter :authenticate, :except => :public
14
- #
15
- # caches_page :public
16
- # caches_action :index, :show
17
- # end
18
- #
19
- # In this example, the +public+ action doesn't require authentication
20
- # so it's possible to use the faster page caching. On the other hand
21
- # +index+ and +show+ require authentication. They can still be cached,
22
- # but we need action caching for them.
23
- #
24
- # Action caching uses fragment caching internally and an around
25
- # filter to do the job. The fragment cache is named according to
26
- # the host and path of the request. A page that is accessed at
27
- # <tt>http://david.example.com/lists/show/1</tt> will result in a fragment named
28
- # <tt>david.example.com/lists/show/1</tt>. This allows the cacher to
29
- # differentiate between <tt>david.example.com/lists/</tt> and
30
- # <tt>jamis.example.com/lists/</tt> -- which is a helpful way of assisting
31
- # the subdomain-as-account-key pattern.
32
- #
33
- # Different representations of the same resource, e.g.
34
- # <tt>http://david.example.com/lists</tt> and
35
- # <tt>http://david.example.com/lists.xml</tt>
36
- # are treated like separate requests and so are cached separately.
37
- # Keep in mind when expiring an action cache that
38
- # <tt>:action => 'lists'</tt> is not the same as
39
- # <tt>:action => 'list', :format => :xml</tt>.
40
- #
41
- # You can modify the default action cache path by passing a
42
- # <tt>:cache_path</tt> option. This will be passed directly to
43
- # <tt>ActionCachePath.path_for</tt>. This is handy for actions with
44
- # multiple possible routes that should be cached differently. If a
45
- # block is given, it is called with the current controller instance.
46
- #
47
- # And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a
48
- # proc that specifies when the action should be cached.
49
- #
50
- # Finally, if you are using memcached, you can also pass <tt>:expires_in</tt>.
51
- #
52
- # The following example depicts some of the points made above:
53
- #
54
- # class ListsController < ApplicationController
55
- # before_filter :authenticate, :except => :public
56
- #
57
- # caches_page :public
58
- #
59
- # caches_action :index, :if => proc do
60
- # !request.format.json? # cache if is not a JSON request
61
- # end
62
- #
63
- # caches_action :show, :cache_path => { :project => 1 },
64
- # :expires_in => 1.hour
65
- #
66
- # caches_action :feed, :cache_path => proc do
67
- # if params[:user_id]
68
- # user_list_url(params[:user_id, params[:id])
69
- # else
70
- # list_url(params[:id])
71
- # end
72
- # end
73
- # end
74
- #
75
- # If you pass <tt>:layout => false</tt>, it will only cache your action
76
- # content. That's useful when your layout has dynamic information.
77
- #
78
- # Warning: If the format of the request is determined by the Accept HTTP
79
- # header the Content-Type of the cached response could be wrong because
80
- # no information about the MIME type is stored in the cache key. So, if
81
- # you first ask for MIME type M in the Accept header, a cache entry is
82
- # created, and then perform a second request to the same resource asking
83
- # for a different MIME type, you'd get the content cached for M.
84
- #
85
- # The <tt>:format</tt> parameter is taken into account though. The safest
86
- # way to cache by MIME type is to pass the format in the route.
87
- module Actions
88
- extend ActiveSupport::Concern
89
-
90
- module ClassMethods
91
- # Declares that +actions+ should be cached.
92
- # See ActionController::Caching::Actions for details.
93
- def caches_action(*actions)
94
- return unless cache_configured?
95
- options = actions.extract_options!
96
- options[:layout] = true unless options.key?(:layout)
97
- filter_options = options.extract!(:if, :unless).merge(:only => actions)
98
- cache_options = options.extract!(:layout, :cache_path).merge(:store_options => options)
99
-
100
- around_filter ActionCacheFilter.new(cache_options), filter_options
101
- end
102
- end
103
-
104
- def _save_fragment(name, options)
105
- content = ""
106
- response_body.each do |parts|
107
- content << parts
108
- end
109
-
110
- if caching_allowed?
111
- write_fragment(name, content, options)
112
- else
113
- content
114
- end
115
- end
116
-
117
- protected
118
- def expire_action(options = {})
119
- return unless cache_configured?
120
-
121
- if options.is_a?(Hash) && options[:action].is_a?(Array)
122
- options[:action].each {|action| expire_action(options.merge(:action => action)) }
123
- else
124
- expire_fragment(ActionCachePath.new(self, options, false).path)
125
- end
126
- end
127
-
128
- class ActionCacheFilter #:nodoc:
129
- def initialize(options, &block)
130
- @cache_path, @store_options, @cache_layout =
131
- options.values_at(:cache_path, :store_options, :layout)
132
- end
133
-
134
- def filter(controller)
135
- path_options = if @cache_path.respond_to?(:call)
136
- controller.instance_exec(controller, &@cache_path)
137
- else
138
- @cache_path
139
- end
140
-
141
- cache_path = ActionCachePath.new(controller, path_options || {})
142
-
143
- body = controller.read_fragment(cache_path.path, @store_options)
144
-
145
- unless body
146
- controller.action_has_layout = false unless @cache_layout
147
- yield
148
- controller.action_has_layout = true
149
- body = controller._save_fragment(cache_path.path, @store_options)
150
- end
151
-
152
- body = controller.render_to_string(:text => body, :layout => true) unless @cache_layout
153
-
154
- controller.response_body = body
155
- controller.content_type = Mime[cache_path.extension || :html]
156
- end
157
- end
158
-
159
- class ActionCachePath
160
- attr_reader :path, :extension
161
-
162
- # If +infer_extension+ is true, the cache path extension is looked up from the request's
163
- # path and format. This is desirable when reading and writing the cache, but not when
164
- # expiring the cache - expire_action should expire the same files regardless of the
165
- # request format.
166
- def initialize(controller, options = {}, infer_extension = true)
167
- if infer_extension
168
- @extension = controller.params[:format]
169
- options.reverse_merge!(:format => @extension) if options.is_a?(Hash)
170
- end
171
-
172
- path = controller.url_for(options).split(%r{://}).last
173
- @path = normalize!(path)
174
- end
175
-
176
- private
177
- def normalize!(path)
178
- path << 'index' if path[-1] == ?/
179
- path << ".#{extension}" if extension and !path.split('?').first.ends_with?(".#{extension}")
180
- URI.parser.unescape(path)
181
- end
182
- end
183
- end
184
- end
185
- end
@@ -1,187 +0,0 @@
1
- require 'fileutils'
2
- require 'active_support/core_ext/class/attribute_accessors'
3
-
4
- module ActionController #:nodoc:
5
- module Caching
6
- # Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server
7
- # can serve without going through Action Pack. This is the fastest way to cache your content as opposed to going dynamically
8
- # through the process of generating the content. Unfortunately, this incredible speed-up is only available to stateless pages
9
- # where all visitors are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are
10
- # a great fit for this approach, but account-based systems where people log in and manipulate their own data are often less
11
- # likely candidates.
12
- #
13
- # Specifying which actions to cache is done through the <tt>caches_page</tt> class method:
14
- #
15
- # class WeblogController < ActionController::Base
16
- # caches_page :show, :new
17
- # end
18
- #
19
- # This will generate cache files such as <tt>weblog/show/5.html</tt> and <tt>weblog/new.html</tt>, which match the URLs used
20
- # that would normally trigger dynamic page generation. Page caching works by configuring a web server to first check for the
21
- # existence of files on disk, and to serve them directly when found, without passing the request through to Action Pack.
22
- # This is much faster than handling the full dynamic request in the usual way.
23
- #
24
- # Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache
25
- # is not restored before another hit is made against it. The API for doing so mimics the options from +url_for+ and friends:
26
- #
27
- # class WeblogController < ActionController::Base
28
- # def update
29
- # List.update(params[:list][:id], params[:list])
30
- # expire_page :action => "show", :id => params[:list][:id]
31
- # redirect_to :action => "show", :id => params[:list][:id]
32
- # end
33
- # end
34
- #
35
- # Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be
36
- # expired.
37
- module Pages
38
- extend ActiveSupport::Concern
39
-
40
- included do
41
- # The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
42
- # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>Rails.root + "/public"</tt>). Changing
43
- # this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
44
- # web server to look in the new location for cached files.
45
- class_attribute :page_cache_directory
46
- self.page_cache_directory ||= ''
47
-
48
- # Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
49
- # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
50
- # If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
51
- # extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
52
- class_attribute :page_cache_extension
53
- self.page_cache_extension ||= '.html'
54
-
55
- # The compression used for gzip. If false (default), the page is not compressed.
56
- # If can be a symbol showing the ZLib compression method, for example, :best_compression
57
- # or :best_speed or an integer configuring the compression level.
58
- class_attribute :page_cache_compression
59
- self.page_cache_compression ||= false
60
- end
61
-
62
- module ClassMethods
63
- # Expires the page that was cached with the +path+ as a key. Example:
64
- # expire_page "/lists/show"
65
- def expire_page(path)
66
- return unless perform_caching
67
- path = page_cache_path(path)
68
-
69
- instrument_page_cache :expire_page, path do
70
- File.delete(path) if File.exist?(path)
71
- File.delete(path + '.gz') if File.exist?(path + '.gz')
72
- end
73
- end
74
-
75
- # Manually cache the +content+ in the key determined by +path+. Example:
76
- # cache_page "I'm the cached content", "/lists/show"
77
- def cache_page(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION)
78
- return unless perform_caching
79
- path = page_cache_path(path, extension)
80
-
81
- instrument_page_cache :write_page, path do
82
- FileUtils.makedirs(File.dirname(path))
83
- File.open(path, "wb+") { |f| f.write(content) }
84
- if gzip
85
- Zlib::GzipWriter.open(path + '.gz', gzip) { |f| f.write(content) }
86
- end
87
- end
88
- end
89
-
90
- # Caches the +actions+ using the page-caching approach that'll store
91
- # the cache in a path within the page_cache_directory that
92
- # matches the triggering url.
93
- #
94
- # You can also pass a :gzip option to override the class configuration one.
95
- #
96
- # Usage:
97
- #
98
- # # cache the index action
99
- # caches_page :index
100
- #
101
- # # cache the index action except for JSON requests
102
- # caches_page :index, :if => Proc.new { |c| !c.request.format.json? }
103
- #
104
- # # don't gzip images
105
- # caches_page :image, :gzip => false
106
- def caches_page(*actions)
107
- return unless perform_caching
108
- options = actions.extract_options!
109
-
110
- gzip_level = options.fetch(:gzip, page_cache_compression)
111
- gzip_level = case gzip_level
112
- when Symbol
113
- Zlib.const_get(gzip_level.to_s.upcase)
114
- when Fixnum
115
- gzip_level
116
- when false
117
- nil
118
- else
119
- Zlib::BEST_COMPRESSION
120
- end
121
-
122
- after_filter({:only => actions}.merge(options)) do |c|
123
- c.cache_page(nil, nil, gzip_level)
124
- end
125
- end
126
-
127
- private
128
- def page_cache_file(path, extension)
129
- name = (path.empty? || path == "/") ? "/index" : URI.parser.unescape(path.chomp('/'))
130
- unless (name.split('/').last || name).include? '.'
131
- name << (extension || self.page_cache_extension)
132
- end
133
- return name
134
- end
135
-
136
- def page_cache_path(path, extension = nil)
137
- page_cache_directory.to_s + page_cache_file(path, extension)
138
- end
139
-
140
- def instrument_page_cache(name, path)
141
- ActiveSupport::Notifications.instrument("#{name}.action_controller", :path => path){ yield }
142
- end
143
- end
144
-
145
- # Expires the page that was cached with the +options+ as a key. Example:
146
- # expire_page :controller => "lists", :action => "show"
147
- def expire_page(options = {})
148
- return unless self.class.perform_caching
149
-
150
- if options.is_a?(Hash)
151
- if options[:action].is_a?(Array)
152
- options[:action].each do |action|
153
- self.class.expire_page(url_for(options.merge(:only_path => true, :action => action)))
154
- end
155
- else
156
- self.class.expire_page(url_for(options.merge(:only_path => true)))
157
- end
158
- else
159
- self.class.expire_page(options)
160
- end
161
- end
162
-
163
- # Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of response.body is used.
164
- # If no options are provided, the url of the current request being handled is used. Example:
165
- # cache_page "I'm the cached content", :controller => "lists", :action => "show"
166
- def cache_page(content = nil, options = nil, gzip = Zlib::BEST_COMPRESSION)
167
- return unless self.class.perform_caching && caching_allowed?
168
-
169
- path = case options
170
- when Hash
171
- url_for(options.merge(:only_path => true, :format => params[:format]))
172
- when String
173
- options
174
- else
175
- request.path
176
- end
177
-
178
- if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
179
- extension = ".#{type_symbol}"
180
- end
181
-
182
- self.class.cache_page(content || response.body, path, extension, gzip)
183
- end
184
-
185
- end
186
- end
187
- end
@@ -1,97 +0,0 @@
1
- module ActionController #:nodoc:
2
- module Caching
3
- # Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
4
- # They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
5
- #
6
- # class ListSweeper < ActionController::Caching::Sweeper
7
- # observe List, Item
8
- #
9
- # def after_save(record)
10
- # list = record.is_a?(List) ? record : record.list
11
- # expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id)
12
- # expire_action(:controller => "lists", :action => "all")
13
- # list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key) }
14
- # end
15
- # end
16
- #
17
- # The sweeper is assigned in the controllers that wish to have its job performed using the <tt>cache_sweeper</tt> class method:
18
- #
19
- # class ListsController < ApplicationController
20
- # caches_action :index, :show, :public, :feed
21
- # cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ]
22
- # end
23
- #
24
- # In the example above, four actions are cached and three actions are responsible for expiring those caches.
25
- #
26
- # You can also name an explicit class in the declaration of a sweeper, which is needed if the sweeper is in a module:
27
- #
28
- # class ListsController < ApplicationController
29
- # caches_action :index, :show, :public, :feed
30
- # cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
31
- # end
32
- module Sweeping
33
- extend ActiveSupport::Concern
34
-
35
- module ClassMethods #:nodoc:
36
- def cache_sweeper(*sweepers)
37
- configuration = sweepers.extract_options!
38
-
39
- sweepers.each do |sweeper|
40
- ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
41
- sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance
42
-
43
- if sweeper_instance.is_a?(Sweeper)
44
- around_filter(sweeper_instance, :only => configuration[:only])
45
- else
46
- after_filter(sweeper_instance, :only => configuration[:only])
47
- end
48
- end
49
- end
50
- end
51
- end
52
-
53
- if defined?(ActiveRecord) and defined?(ActiveRecord::Observer)
54
- class Sweeper < ActiveRecord::Observer #:nodoc:
55
- attr_accessor :controller
56
-
57
- def before(controller)
58
- self.controller = controller
59
- callback(:before) if controller.perform_caching
60
- true # before method from sweeper should always return true
61
- end
62
-
63
- def after(controller)
64
- self.controller = controller
65
- callback(:after) if controller.perform_caching
66
- # Clean up, so that the controller can be collected after this request
67
- self.controller = nil
68
- end
69
-
70
- protected
71
- # gets the action cache path for the given options.
72
- def action_path_for(options)
73
- Actions::ActionCachePath.new(controller, options).path
74
- end
75
-
76
- # Retrieve instance variables set in the controller.
77
- def assigns(key)
78
- controller.instance_variable_get("@#{key}")
79
- end
80
-
81
- private
82
- def callback(timing)
83
- controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
84
- action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"
85
-
86
- __send__(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
87
- __send__(action_callback_method_name) if respond_to?(action_callback_method_name, true)
88
- end
89
-
90
- def method_missing(method, *arguments, &block)
91
- return unless @controller
92
- @controller.__send__(method, *arguments, &block)
93
- end
94
- end
95
- end
96
- end
97
- end