actionpack 3.2.22.5 → 5.2.4

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 (271) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +279 -603
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -297
  5. data/lib/abstract_controller/asset_paths.rb +4 -2
  6. data/lib/abstract_controller/base.rb +82 -52
  7. data/lib/abstract_controller/caching/fragments.rb +166 -0
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +117 -103
  10. data/lib/abstract_controller/collector.rb +18 -7
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +65 -38
  13. data/lib/abstract_controller/logger.rb +3 -2
  14. data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
  15. data/lib/abstract_controller/rendering.rb +77 -129
  16. data/lib/abstract_controller/translation.rb +21 -3
  17. data/lib/abstract_controller/url_for.rb +9 -7
  18. data/lib/abstract_controller.rb +12 -13
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/base.rb +81 -40
  22. data/lib/action_controller/caching.rb +22 -62
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +30 -18
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +190 -47
  27. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  28. data/lib/action_controller/metal/cookies.rb +3 -3
  29. data/lib/action_controller/metal/data_streaming.rb +40 -65
  30. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  31. data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
  32. data/lib/action_controller/metal/exceptions.rb +19 -12
  33. data/lib/action_controller/metal/flash.rb +42 -9
  34. data/lib/action_controller/metal/force_ssl.rb +79 -19
  35. data/lib/action_controller/metal/head.rb +35 -10
  36. data/lib/action_controller/metal/helpers.rb +31 -21
  37. data/lib/action_controller/metal/http_authentication.rb +182 -134
  38. data/lib/action_controller/metal/implicit_render.rb +62 -8
  39. data/lib/action_controller/metal/instrumentation.rb +28 -26
  40. data/lib/action_controller/metal/live.rb +312 -0
  41. data/lib/action_controller/metal/mime_responds.rb +159 -163
  42. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  43. data/lib/action_controller/metal/params_wrapper.rb +146 -93
  44. data/lib/action_controller/metal/redirecting.rb +80 -56
  45. data/lib/action_controller/metal/renderers.rb +119 -47
  46. data/lib/action_controller/metal/rendering.rb +89 -32
  47. data/lib/action_controller/metal/request_forgery_protection.rb +373 -41
  48. data/lib/action_controller/metal/rescue.rb +9 -16
  49. data/lib/action_controller/metal/streaming.rb +39 -45
  50. data/lib/action_controller/metal/strong_parameters.rb +1086 -0
  51. data/lib/action_controller/metal/testing.rb +8 -29
  52. data/lib/action_controller/metal/url_for.rb +43 -32
  53. data/lib/action_controller/metal.rb +112 -106
  54. data/lib/action_controller/railtie.rb +56 -18
  55. data/lib/action_controller/railties/helpers.rb +24 -0
  56. data/lib/action_controller/renderer.rb +117 -0
  57. data/lib/action_controller/template_assertions.rb +11 -0
  58. data/lib/action_controller/test_case.rb +402 -347
  59. data/lib/action_controller.rb +31 -30
  60. data/lib/action_dispatch/http/cache.rb +133 -34
  61. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  62. data/lib/action_dispatch/http/filter_parameters.rb +40 -24
  63. data/lib/action_dispatch/http/filter_redirect.rb +37 -0
  64. data/lib/action_dispatch/http/headers.rb +117 -16
  65. data/lib/action_dispatch/http/mime_negotiation.rb +98 -33
  66. data/lib/action_dispatch/http/mime_type.rb +198 -146
  67. data/lib/action_dispatch/http/mime_types.rb +22 -7
  68. data/lib/action_dispatch/http/parameter_filter.rb +61 -49
  69. data/lib/action_dispatch/http/parameters.rb +94 -51
  70. data/lib/action_dispatch/http/rack_cache.rb +4 -3
  71. data/lib/action_dispatch/http/request.rb +262 -117
  72. data/lib/action_dispatch/http/response.rb +400 -86
  73. data/lib/action_dispatch/http/upload.rb +66 -29
  74. data/lib/action_dispatch/http/url.rb +232 -60
  75. data/lib/action_dispatch/journey/formatter.rb +189 -0
  76. data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
  77. data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
  78. data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
  79. data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
  80. data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
  81. data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
  82. data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
  83. data/lib/action_dispatch/journey/nodes/node.rb +140 -0
  84. data/lib/action_dispatch/journey/parser.rb +199 -0
  85. data/lib/action_dispatch/journey/parser.y +50 -0
  86. data/lib/action_dispatch/journey/parser_extras.rb +31 -0
  87. data/lib/action_dispatch/journey/path/pattern.rb +199 -0
  88. data/lib/action_dispatch/journey/route.rb +203 -0
  89. data/lib/action_dispatch/journey/router/utils.rb +102 -0
  90. data/lib/action_dispatch/journey/router.rb +156 -0
  91. data/lib/action_dispatch/journey/routes.rb +82 -0
  92. data/lib/action_dispatch/journey/scanner.rb +64 -0
  93. data/lib/action_dispatch/journey/visitors.rb +268 -0
  94. data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
  95. data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
  96. data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
  97. data/lib/action_dispatch/journey.rb +7 -0
  98. data/lib/action_dispatch/middleware/callbacks.rb +17 -13
  99. data/lib/action_dispatch/middleware/cookies.rb +494 -162
  100. data/lib/action_dispatch/middleware/debug_exceptions.rb +176 -53
  101. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  102. data/lib/action_dispatch/middleware/exception_wrapper.rb +103 -38
  103. data/lib/action_dispatch/middleware/executor.rb +21 -0
  104. data/lib/action_dispatch/middleware/flash.rb +128 -91
  105. data/lib/action_dispatch/middleware/public_exceptions.rb +43 -16
  106. data/lib/action_dispatch/middleware/reloader.rb +6 -83
  107. data/lib/action_dispatch/middleware/remote_ip.rb +151 -49
  108. data/lib/action_dispatch/middleware/request_id.rb +19 -15
  109. data/lib/action_dispatch/middleware/session/abstract_store.rb +38 -34
  110. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -9
  111. data/lib/action_dispatch/middleware/session/cookie_store.rb +94 -44
  112. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -4
  113. data/lib/action_dispatch/middleware/show_exceptions.rb +36 -61
  114. data/lib/action_dispatch/middleware/ssl.rb +150 -0
  115. data/lib/action_dispatch/middleware/stack.rb +33 -41
  116. data/lib/action_dispatch/middleware/static.rb +92 -48
  117. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
  122. data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
  123. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +134 -5
  128. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
  136. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
  137. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
  138. data/lib/action_dispatch/railtie.rb +29 -8
  139. data/lib/action_dispatch/request/session.rb +234 -0
  140. data/lib/action_dispatch/request/utils.rb +78 -0
  141. data/lib/action_dispatch/routing/endpoint.rb +17 -0
  142. data/lib/action_dispatch/routing/inspector.rb +225 -0
  143. data/lib/action_dispatch/routing/mapper.rb +1329 -582
  144. data/lib/action_dispatch/routing/polymorphic_routes.rb +237 -94
  145. data/lib/action_dispatch/routing/redirection.rb +120 -50
  146. data/lib/action_dispatch/routing/route_set.rb +545 -322
  147. data/lib/action_dispatch/routing/routes_proxy.rb +37 -7
  148. data/lib/action_dispatch/routing/url_for.rb +103 -34
  149. data/lib/action_dispatch/routing.rb +66 -99
  150. data/lib/action_dispatch/system_test_case.rb +147 -0
  151. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  152. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  153. data/lib/action_dispatch/system_testing/server.rb +31 -0
  154. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  156. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  158. data/lib/action_dispatch/testing/assertions/response.rb +53 -42
  159. data/lib/action_dispatch/testing/assertions/routing.rb +79 -74
  160. data/lib/action_dispatch/testing/assertions.rb +15 -9
  161. data/lib/action_dispatch/testing/integration.rb +361 -207
  162. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  163. data/lib/action_dispatch/testing/test_process.rb +28 -19
  164. data/lib/action_dispatch/testing/test_request.rb +30 -33
  165. data/lib/action_dispatch/testing/test_response.rb +35 -11
  166. data/lib/action_dispatch.rb +42 -32
  167. data/lib/action_pack/gem_version.rb +17 -0
  168. data/lib/action_pack/version.rb +7 -7
  169. data/lib/action_pack.rb +4 -2
  170. metadata +116 -175
  171. data/lib/abstract_controller/layouts.rb +0 -423
  172. data/lib/abstract_controller/view_paths.rb +0 -96
  173. data/lib/action_controller/caching/actions.rb +0 -185
  174. data/lib/action_controller/caching/fragments.rb +0 -127
  175. data/lib/action_controller/caching/pages.rb +0 -187
  176. data/lib/action_controller/caching/sweeping.rb +0 -97
  177. data/lib/action_controller/deprecated/integration_test.rb +0 -2
  178. data/lib/action_controller/deprecated/performance_test.rb +0 -1
  179. data/lib/action_controller/deprecated.rb +0 -3
  180. data/lib/action_controller/metal/compatibility.rb +0 -65
  181. data/lib/action_controller/metal/hide_actions.rb +0 -41
  182. data/lib/action_controller/metal/rack_delegation.rb +0 -26
  183. data/lib/action_controller/metal/responder.rb +0 -286
  184. data/lib/action_controller/metal/session_management.rb +0 -14
  185. data/lib/action_controller/middleware.rb +0 -39
  186. data/lib/action_controller/railties/paths.rb +0 -25
  187. data/lib/action_controller/record_identifier.rb +0 -85
  188. data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
  189. data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
  190. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
  191. data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
  192. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
  193. data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
  194. data/lib/action_controller/vendor/html-scanner.rb +0 -20
  195. data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
  196. data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
  197. data/lib/action_dispatch/middleware/head.rb +0 -18
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -75
  199. data/lib/action_dispatch/middleware/rescue.rb +0 -26
  200. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
  201. data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
  202. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
  203. data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
  204. data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
  205. data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
  206. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
  207. data/lib/action_dispatch/testing/assertions/dom.rb +0 -37
  208. data/lib/action_dispatch/testing/assertions/selector.rb +0 -435
  209. data/lib/action_dispatch/testing/assertions/tag.rb +0 -138
  210. data/lib/action_dispatch/testing/performance_test.rb +0 -10
  211. data/lib/action_view/asset_paths.rb +0 -142
  212. data/lib/action_view/base.rb +0 -220
  213. data/lib/action_view/buffers.rb +0 -43
  214. data/lib/action_view/context.rb +0 -36
  215. data/lib/action_view/flows.rb +0 -79
  216. data/lib/action_view/helpers/active_model_helper.rb +0 -50
  217. data/lib/action_view/helpers/asset_paths.rb +0 -7
  218. data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
  219. data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
  220. data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
  221. data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
  222. data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
  223. data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
  224. data/lib/action_view/helpers/cache_helper.rb +0 -64
  225. data/lib/action_view/helpers/capture_helper.rb +0 -203
  226. data/lib/action_view/helpers/controller_helper.rb +0 -25
  227. data/lib/action_view/helpers/csrf_helper.rb +0 -32
  228. data/lib/action_view/helpers/date_helper.rb +0 -1062
  229. data/lib/action_view/helpers/debug_helper.rb +0 -40
  230. data/lib/action_view/helpers/form_helper.rb +0 -1486
  231. data/lib/action_view/helpers/form_options_helper.rb +0 -658
  232. data/lib/action_view/helpers/form_tag_helper.rb +0 -685
  233. data/lib/action_view/helpers/javascript_helper.rb +0 -110
  234. data/lib/action_view/helpers/number_helper.rb +0 -622
  235. data/lib/action_view/helpers/output_safety_helper.rb +0 -38
  236. data/lib/action_view/helpers/record_tag_helper.rb +0 -111
  237. data/lib/action_view/helpers/rendering_helper.rb +0 -92
  238. data/lib/action_view/helpers/sanitize_helper.rb +0 -259
  239. data/lib/action_view/helpers/tag_helper.rb +0 -167
  240. data/lib/action_view/helpers/text_helper.rb +0 -426
  241. data/lib/action_view/helpers/translation_helper.rb +0 -91
  242. data/lib/action_view/helpers/url_helper.rb +0 -693
  243. data/lib/action_view/helpers.rb +0 -60
  244. data/lib/action_view/locale/en.yml +0 -160
  245. data/lib/action_view/log_subscriber.rb +0 -28
  246. data/lib/action_view/lookup_context.rb +0 -258
  247. data/lib/action_view/path_set.rb +0 -101
  248. data/lib/action_view/railtie.rb +0 -55
  249. data/lib/action_view/renderer/abstract_renderer.rb +0 -41
  250. data/lib/action_view/renderer/partial_renderer.rb +0 -415
  251. data/lib/action_view/renderer/renderer.rb +0 -61
  252. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
  253. data/lib/action_view/renderer/template_renderer.rb +0 -95
  254. data/lib/action_view/template/error.rb +0 -128
  255. data/lib/action_view/template/handlers/builder.rb +0 -26
  256. data/lib/action_view/template/handlers/erb.rb +0 -125
  257. data/lib/action_view/template/handlers.rb +0 -50
  258. data/lib/action_view/template/resolver.rb +0 -298
  259. data/lib/action_view/template/text.rb +0 -30
  260. data/lib/action_view/template.rb +0 -337
  261. data/lib/action_view/test_case.rb +0 -246
  262. data/lib/action_view/testing/resolvers.rb +0 -49
  263. data/lib/action_view.rb +0 -84
  264. data/lib/sprockets/assets.rake +0 -99
  265. data/lib/sprockets/bootstrap.rb +0 -37
  266. data/lib/sprockets/compressors.rb +0 -83
  267. data/lib/sprockets/helpers/isolated_helper.rb +0 -13
  268. data/lib/sprockets/helpers/rails_helper.rb +0 -182
  269. data/lib/sprockets/helpers.rb +0 -6
  270. data/lib/sprockets/railtie.rb +0 -62
  271. data/lib/sprockets/static_compiler.rb +0 -56
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractController
4
+ module Caching
5
+ # Fragment caching is used for caching various blocks within
6
+ # views without caching the entire action as a whole. This is
7
+ # useful when certain elements of an action change frequently or
8
+ # depend on complicated state while other parts rarely change or
9
+ # can be shared amongst multiple parties. The caching is done using
10
+ # the +cache+ helper available in the Action View. See
11
+ # ActionView::Helpers::CacheHelper for more information.
12
+ #
13
+ # While it's strongly recommended that you use key-based cache
14
+ # expiration (see links in CacheHelper for more information),
15
+ # it is also possible to manually expire caches. For example:
16
+ #
17
+ # expire_fragment('name_of_cache')
18
+ module Fragments
19
+ extend ActiveSupport::Concern
20
+
21
+ included do
22
+ if respond_to?(:class_attribute)
23
+ class_attribute :fragment_cache_keys
24
+ else
25
+ mattr_writer :fragment_cache_keys
26
+ end
27
+
28
+ self.fragment_cache_keys = []
29
+
30
+ if respond_to?(:helper_method)
31
+ helper_method :fragment_cache_key
32
+ helper_method :combined_fragment_cache_key
33
+ end
34
+ end
35
+
36
+ module ClassMethods
37
+ # Allows you to specify controller-wide key prefixes for
38
+ # cache fragments. Pass either a constant +value+, or a block
39
+ # which computes a value each time a cache key is generated.
40
+ #
41
+ # For example, you may want to prefix all fragment cache keys
42
+ # with a global version identifier, so you can easily
43
+ # invalidate all caches.
44
+ #
45
+ # class ApplicationController
46
+ # fragment_cache_key "v1"
47
+ # end
48
+ #
49
+ # When it's time to invalidate all fragments, simply change
50
+ # the string constant. Or, progressively roll out the cache
51
+ # invalidation using a computed value:
52
+ #
53
+ # class ApplicationController
54
+ # fragment_cache_key do
55
+ # @account.id.odd? ? "v1" : "v2"
56
+ # end
57
+ # end
58
+ def fragment_cache_key(value = nil, &key)
59
+ self.fragment_cache_keys += [key || -> { value }]
60
+ end
61
+ end
62
+
63
+ # Given a key (as described in +expire_fragment+), returns
64
+ # a key suitable for use in reading, writing, or expiring a
65
+ # cached fragment. All keys begin with <tt>views/</tt>,
66
+ # followed by any controller-wide key prefix values, ending
67
+ # with the specified +key+ value. The key is expanded using
68
+ # ActiveSupport::Cache.expand_cache_key.
69
+ def fragment_cache_key(key)
70
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
71
+ Calling fragment_cache_key directly is deprecated and will be removed in Rails 6.0.
72
+ All fragment accessors now use the combined_fragment_cache_key method that retains the key as an array,
73
+ such that the caching stores can interrogate the parts for cache versions used in
74
+ recyclable cache keys.
75
+ MSG
76
+
77
+ head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
78
+ tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
79
+ ActiveSupport::Cache.expand_cache_key([*head, *tail], :views)
80
+ end
81
+
82
+ # Given a key (as described in +expire_fragment+), returns
83
+ # a key array suitable for use in reading, writing, or expiring a
84
+ # cached fragment. All keys begin with <tt>:views</tt>,
85
+ # followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set,
86
+ # followed by any controller-wide key prefix values, ending
87
+ # with the specified +key+ value.
88
+ def combined_fragment_cache_key(key)
89
+ head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
90
+ tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
91
+ [ :views, (ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]), *head, *tail ].compact
92
+ end
93
+
94
+ # Writes +content+ to the location signified by
95
+ # +key+ (see +expire_fragment+ for acceptable formats).
96
+ def write_fragment(key, content, options = nil)
97
+ return content unless cache_configured?
98
+
99
+ key = combined_fragment_cache_key(key)
100
+ instrument_fragment_cache :write_fragment, key do
101
+ content = content.to_str
102
+ cache_store.write(key, content, options)
103
+ end
104
+ content
105
+ end
106
+
107
+ # Reads a cached fragment from the location signified by +key+
108
+ # (see +expire_fragment+ for acceptable formats).
109
+ def read_fragment(key, options = nil)
110
+ return unless cache_configured?
111
+
112
+ key = combined_fragment_cache_key(key)
113
+ instrument_fragment_cache :read_fragment, key do
114
+ result = cache_store.read(key, options)
115
+ result.respond_to?(:html_safe) ? result.html_safe : result
116
+ end
117
+ end
118
+
119
+ # Check if a cached fragment from the location signified by
120
+ # +key+ exists (see +expire_fragment+ for acceptable formats).
121
+ def fragment_exist?(key, options = nil)
122
+ return unless cache_configured?
123
+ key = combined_fragment_cache_key(key)
124
+
125
+ instrument_fragment_cache :exist_fragment?, key do
126
+ cache_store.exist?(key, options)
127
+ end
128
+ end
129
+
130
+ # Removes fragments from the cache.
131
+ #
132
+ # +key+ can take one of three forms:
133
+ #
134
+ # * String - This would normally take the form of a path, like
135
+ # <tt>pages/45/notes</tt>.
136
+ # * Hash - Treated as an implicit call to +url_for+, like
137
+ # <tt>{ controller: 'pages', action: 'notes', id: 45}</tt>
138
+ # * Regexp - Will remove any fragment that matches, so
139
+ # <tt>%r{pages/\d*/notes}</tt> might remove all notes. Make sure you
140
+ # don't use anchors in the regex (<tt>^</tt> or <tt>$</tt>) because
141
+ # the actual filename matched looks like
142
+ # <tt>./cache/filename/path.cache</tt>. Note: Regexp expiration is
143
+ # only supported on caches that can iterate over all keys (unlike
144
+ # memcached).
145
+ #
146
+ # +options+ is passed through to the cache store's +delete+
147
+ # method (or <tt>delete_matched</tt>, for Regexp keys).
148
+ def expire_fragment(key, options = nil)
149
+ return unless cache_configured?
150
+ key = combined_fragment_cache_key(key) unless key.is_a?(Regexp)
151
+
152
+ instrument_fragment_cache :expire_fragment, key do
153
+ if key.is_a?(Regexp)
154
+ cache_store.delete_matched(key, options)
155
+ else
156
+ cache_store.delete(key, options)
157
+ end
158
+ end
159
+ end
160
+
161
+ def instrument_fragment_cache(name, key) # :nodoc:
162
+ ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key)) { yield }
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractController
4
+ module Caching
5
+ extend ActiveSupport::Concern
6
+ extend ActiveSupport::Autoload
7
+
8
+ eager_autoload do
9
+ autoload :Fragments
10
+ end
11
+
12
+ module ConfigMethods
13
+ def cache_store
14
+ config.cache_store
15
+ end
16
+
17
+ def cache_store=(store)
18
+ config.cache_store = ActiveSupport::Cache.lookup_store(store)
19
+ end
20
+
21
+ private
22
+ def cache_configured?
23
+ perform_caching && cache_store
24
+ end
25
+ end
26
+
27
+ include ConfigMethods
28
+ include AbstractController::Caching::Fragments
29
+
30
+ included do
31
+ extend ConfigMethods
32
+
33
+ config_accessor :default_static_extension
34
+ self.default_static_extension ||= ".html"
35
+
36
+ config_accessor :perform_caching
37
+ self.perform_caching = true if perform_caching.nil?
38
+
39
+ config_accessor :enable_fragment_cache_logging
40
+ self.enable_fragment_cache_logging = false
41
+
42
+ class_attribute :_view_cache_dependencies, default: []
43
+ helper_method :view_cache_dependencies if respond_to?(:helper_method)
44
+ end
45
+
46
+ module ClassMethods
47
+ def view_cache_dependency(&dependency)
48
+ self._view_cache_dependencies += [dependency]
49
+ end
50
+ end
51
+
52
+ def view_cache_dependencies
53
+ self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact
54
+ end
55
+
56
+ private
57
+ # Convenience accessor.
58
+ def cache(key, options = {}, &block) # :doc:
59
+ if cache_configured?
60
+ cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block)
61
+ else
62
+ yield
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,4 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AbstractController
4
+ # = Abstract Controller Callbacks
5
+ #
6
+ # Abstract Controller provides hooks during the life cycle of a controller action.
7
+ # Callbacks allow you to trigger logic during this cycle. Available callbacks are:
8
+ #
9
+ # * <tt>after_action</tt>
10
+ # * <tt>append_after_action</tt>
11
+ # * <tt>append_around_action</tt>
12
+ # * <tt>append_before_action</tt>
13
+ # * <tt>around_action</tt>
14
+ # * <tt>before_action</tt>
15
+ # * <tt>prepend_after_action</tt>
16
+ # * <tt>prepend_around_action</tt>
17
+ # * <tt>prepend_before_action</tt>
18
+ # * <tt>skip_after_action</tt>
19
+ # * <tt>skip_around_action</tt>
20
+ # * <tt>skip_before_action</tt>
21
+ #
22
+ # NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
23
+ #
2
24
  module Callbacks
3
25
  extend ActiveSupport::Concern
4
26
 
@@ -8,50 +30,50 @@ module AbstractController
8
30
  include ActiveSupport::Callbacks
9
31
 
10
32
  included do
11
- define_callbacks :process_action, :terminator => "response_body"
33
+ define_callbacks :process_action,
34
+ terminator: ->(controller, result_lambda) { result_lambda.call; controller.performed? },
35
+ skip_after_callbacks_if_terminated: true
12
36
  end
13
37
 
14
- # Override AbstractController::Base's process_action to run the
15
- # process_action callbacks around the normal behavior.
38
+ # Override <tt>AbstractController::Base#process_action</tt> to run the
39
+ # <tt>process_action</tt> callbacks around the normal behavior.
16
40
  def process_action(*args)
17
- run_callbacks(:process_action, action_name) do
41
+ run_callbacks(:process_action) do
18
42
  super
19
43
  end
20
44
  end
21
45
 
22
46
  module ClassMethods
23
- # If :only or :except are used, convert the options into the
24
- # primitive form (:per_key) used by ActiveSupport::Callbacks.
25
- # The basic idea is that :only => :index gets converted to
26
- # :if => proc {|c| c.action_name == "index" }, but that the
27
- # proc is only evaluated once per action for the lifetime of
28
- # a Rails process.
47
+ # If +:only+ or +:except+ are used, convert the options into the
48
+ # +:if+ and +:unless+ options of ActiveSupport::Callbacks.
49
+ #
50
+ # The basic idea is that <tt>:only => :index</tt> gets converted to
51
+ # <tt>:if => proc {|c| c.action_name == "index" }</tt>.
52
+ #
53
+ # Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they
54
+ # are used together.
55
+ #
56
+ # only: :index, if: -> { true } # the :if option will be ignored.
57
+ #
58
+ # Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they
59
+ # are used together.
60
+ #
61
+ # except: :index, if: -> { true } # the :except option will be ignored.
29
62
  #
30
63
  # ==== Options
31
- # * <tt>only</tt> - The callback should be run only for this action
32
- # * <tt>except</tt> - The callback should be run for all actions except this action
64
+ # * <tt>only</tt> - The callback should be run only for this action.
65
+ # * <tt>except</tt> - The callback should be run for all actions except this action.
33
66
  def _normalize_callback_options(options)
34
- if only = options[:only]
35
- only = Array(only).map {|o| "action_name == '#{o}'"}.join(" || ")
36
- options[:per_key] = {:if => only}
37
- end
38
- if except = options[:except]
39
- except = Array(except).map {|e| "action_name == '#{e}'"}.join(" || ")
40
- options[:per_key] = {:unless => except}
41
- end
67
+ _normalize_callback_option(options, :only, :if)
68
+ _normalize_callback_option(options, :except, :unless)
42
69
  end
43
70
 
44
- # Skip before, after, and around filters matching any of the names
45
- #
46
- # ==== Parameters
47
- # * <tt>names</tt> - A list of valid names that could be used for
48
- # callbacks. Note that skipping uses Ruby equality, so it's
49
- # impossible to skip a callback defined using an anonymous proc
50
- # using #skip_filter
51
- def skip_filter(*names, &blk)
52
- skip_before_filter(*names)
53
- skip_after_filter(*names)
54
- skip_around_filter(*names)
71
+ def _normalize_callback_option(options, from, to) # :nodoc:
72
+ if from = options[from]
73
+ _from = Array(from).map(&:to_s).to_set
74
+ from = proc { |c| _from.include? c.action_name }
75
+ options[to] = Array(options[to]).unshift(from)
76
+ end
55
77
  end
56
78
 
57
79
  # Take callback names and an optional callback proc, normalize them,
@@ -64,10 +86,10 @@ module AbstractController
64
86
  # * <tt>block</tt> - A proc that should be added to the callbacks.
65
87
  #
66
88
  # ==== Block Parameters
67
- # * <tt>name</tt> - The callback to be added
68
- # * <tt>options</tt> - A hash of options to be used when adding the callback
69
- def _insert_callbacks(callbacks, block)
70
- options = callbacks.last.is_a?(Hash) ? callbacks.pop : {}
89
+ # * <tt>name</tt> - The callback to be added.
90
+ # * <tt>options</tt> - A hash of options to be used when adding the callback.
91
+ def _insert_callbacks(callbacks, block = nil)
92
+ options = callbacks.extract_options!
71
93
  _normalize_callback_options(options)
72
94
  callbacks.push(block) if block
73
95
  callbacks.each do |callback|
@@ -76,122 +98,114 @@ module AbstractController
76
98
  end
77
99
 
78
100
  ##
79
- # :method: before_filter
101
+ # :method: before_action
80
102
  #
81
- # :call-seq: before_filter(names, block)
103
+ # :call-seq: before_action(names, block)
82
104
  #
83
- # Append a before filter. See _insert_callbacks for parameter details.
105
+ # Append a callback before actions. See _insert_callbacks for parameter details.
84
106
 
85
107
  ##
86
- # :method: prepend_before_filter
108
+ # :method: prepend_before_action
87
109
  #
88
- # :call-seq: prepend_before_filter(names, block)
110
+ # :call-seq: prepend_before_action(names, block)
89
111
  #
90
- # Prepend a before filter. See _insert_callbacks for parameter details.
112
+ # Prepend a callback before actions. See _insert_callbacks for parameter details.
91
113
 
92
114
  ##
93
- # :method: skip_before_filter
115
+ # :method: skip_before_action
94
116
  #
95
- # :call-seq: skip_before_filter(names, block)
117
+ # :call-seq: skip_before_action(names)
96
118
  #
97
- # Skip a before filter. See _insert_callbacks for parameter details.
119
+ # Skip a callback before actions. See _insert_callbacks for parameter details.
98
120
 
99
121
  ##
100
- # :method: append_before_filter
122
+ # :method: append_before_action
101
123
  #
102
- # :call-seq: append_before_filter(names, block)
124
+ # :call-seq: append_before_action(names, block)
103
125
  #
104
- # Append a before filter. See _insert_callbacks for parameter details.
126
+ # Append a callback before actions. See _insert_callbacks for parameter details.
105
127
 
106
128
  ##
107
- # :method: after_filter
129
+ # :method: after_action
108
130
  #
109
- # :call-seq: after_filter(names, block)
131
+ # :call-seq: after_action(names, block)
110
132
  #
111
- # Append an after filter. See _insert_callbacks for parameter details.
133
+ # Append a callback after actions. See _insert_callbacks for parameter details.
112
134
 
113
135
  ##
114
- # :method: prepend_after_filter
136
+ # :method: prepend_after_action
115
137
  #
116
- # :call-seq: prepend_after_filter(names, block)
138
+ # :call-seq: prepend_after_action(names, block)
117
139
  #
118
- # Prepend an after filter. See _insert_callbacks for parameter details.
140
+ # Prepend a callback after actions. See _insert_callbacks for parameter details.
119
141
 
120
142
  ##
121
- # :method: skip_after_filter
143
+ # :method: skip_after_action
122
144
  #
123
- # :call-seq: skip_after_filter(names, block)
145
+ # :call-seq: skip_after_action(names)
124
146
  #
125
- # Skip an after filter. See _insert_callbacks for parameter details.
147
+ # Skip a callback after actions. See _insert_callbacks for parameter details.
126
148
 
127
149
  ##
128
- # :method: append_after_filter
150
+ # :method: append_after_action
129
151
  #
130
- # :call-seq: append_after_filter(names, block)
152
+ # :call-seq: append_after_action(names, block)
131
153
  #
132
- # Append an after filter. See _insert_callbacks for parameter details.
154
+ # Append a callback after actions. See _insert_callbacks for parameter details.
133
155
 
134
156
  ##
135
- # :method: around_filter
157
+ # :method: around_action
136
158
  #
137
- # :call-seq: around_filter(names, block)
159
+ # :call-seq: around_action(names, block)
138
160
  #
139
- # Append an around filter. See _insert_callbacks for parameter details.
161
+ # Append a callback around actions. See _insert_callbacks for parameter details.
140
162
 
141
163
  ##
142
- # :method: prepend_around_filter
164
+ # :method: prepend_around_action
143
165
  #
144
- # :call-seq: prepend_around_filter(names, block)
166
+ # :call-seq: prepend_around_action(names, block)
145
167
  #
146
- # Prepend an around filter. See _insert_callbacks for parameter details.
168
+ # Prepend a callback around actions. See _insert_callbacks for parameter details.
147
169
 
148
170
  ##
149
- # :method: skip_around_filter
171
+ # :method: skip_around_action
150
172
  #
151
- # :call-seq: skip_around_filter(names, block)
173
+ # :call-seq: skip_around_action(names)
152
174
  #
153
- # Skip an around filter. See _insert_callbacks for parameter details.
175
+ # Skip a callback around actions. See _insert_callbacks for parameter details.
154
176
 
155
177
  ##
156
- # :method: append_around_filter
178
+ # :method: append_around_action
157
179
  #
158
- # :call-seq: append_around_filter(names, block)
180
+ # :call-seq: append_around_action(names, block)
159
181
  #
160
- # Append an around filter. See _insert_callbacks for parameter details.
182
+ # Append a callback around actions. See _insert_callbacks for parameter details.
161
183
 
162
- # set up before_filter, prepend_before_filter, skip_before_filter, etc.
184
+ # set up before_action, prepend_before_action, skip_before_action, etc.
163
185
  # for each of before, after, and around.
164
- [:before, :after, :around].each do |filter|
165
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
166
- # Append a before, after or around filter. See _insert_callbacks
167
- # for details on the allowed parameters.
168
- def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk)
169
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
170
- options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array.wrap(options[:if]) << "!halted") if false
171
- set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before, name, options)
172
- end # end
173
- end # end
174
-
175
- # Prepend a before, after or around filter. See _insert_callbacks
176
- # for details on the allowed parameters.
177
- def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk)
178
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
179
- options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array.wrap(options[:if]) << "!halted") if false
180
- set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
181
- end # end
182
- end # end
183
-
184
- # Skip a before, after or around filter. See _insert_callbacks
185
- # for details on the allowed parameters.
186
- def skip_#{filter}_filter(*names, &blk) # def skip_before_filter(*names, &blk)
187
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
188
- skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options)
189
- end # end
190
- end # end
191
-
192
- # *_filter is the same as append_*_filter
193
- alias_method :append_#{filter}_filter, :#{filter}_filter # alias_method :append_before_filter, :before_filter
194
- RUBY_EVAL
186
+ [:before, :after, :around].each do |callback|
187
+ define_method "#{callback}_action" do |*names, &blk|
188
+ _insert_callbacks(names, blk) do |name, options|
189
+ set_callback(:process_action, callback, name, options)
190
+ end
191
+ end
192
+
193
+ define_method "prepend_#{callback}_action" do |*names, &blk|
194
+ _insert_callbacks(names, blk) do |name, options|
195
+ set_callback(:process_action, callback, name, options.merge(prepend: true))
196
+ end
197
+ end
198
+
199
+ # Skip a before, after or around callback. See _insert_callbacks
200
+ # for details on the allowed parameters.
201
+ define_method "skip_#{callback}_action" do |*names|
202
+ _insert_callbacks(names) do |name, options|
203
+ skip_callback(:process_action, callback, name, options)
204
+ end
205
+ end
206
+
207
+ # *_action is the same as append_*_action
208
+ alias_method :"append_#{callback}_action", :"#{callback}_action"
195
209
  end
196
210
  end
197
211
  end
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_dispatch/http/mime_type"
2
4
 
3
5
  module AbstractController
4
6
  module Collector
5
7
  def self.generate_method_for_mime(mime)
6
8
  sym = mime.is_a?(Symbol) ? mime : mime.to_sym
7
- const = sym.to_s.upcase
8
9
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
9
- def #{sym}(*args, &block) # def html(*args, &block)
10
- custom(Mime::#{const}, *args, &block) # custom(Mime::HTML, *args, &block)
11
- end # end
10
+ def #{sym}(*args, &block)
11
+ custom(Mime[:#{sym}], *args, &block)
12
+ end
12
13
  RUBY
13
14
  end
14
15
 
@@ -16,10 +17,20 @@ module AbstractController
16
17
  generate_method_for_mime(mime)
17
18
  end
18
19
 
19
- protected
20
+ Mime::Type.register_callback do |mime|
21
+ generate_method_for_mime(mime) unless instance_methods.include?(mime.to_sym)
22
+ end
23
+
24
+ private
20
25
 
21
26
  def method_missing(symbol, &block)
22
- mime_constant = Mime.const_get(symbol.to_s.upcase)
27
+ unless mime_constant = Mime[symbol]
28
+ raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
29
+ "http://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
30
+ "If you meant to respond to a variant like :tablet or :phone, not a custom format, " \
31
+ "be sure to nest your variant response within a format response: " \
32
+ "format.html { |html| html.tablet { ... } }"
33
+ end
23
34
 
24
35
  if Mime::SET.include?(mime_constant)
25
36
  AbstractController::Collector.generate_method_for_mime(mime_constant)
@@ -29,4 +40,4 @@ module AbstractController
29
40
  end
30
41
  end
31
42
  end
32
- end
43
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractController
4
+ class Error < StandardError #:nodoc:
5
+ end
6
+ end