actionpack 7.1.3.4 → 7.2.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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -541
  3. data/lib/abstract_controller/asset_paths.rb +2 -0
  4. data/lib/abstract_controller/base.rb +102 -98
  5. data/lib/abstract_controller/caching/fragments.rb +50 -53
  6. data/lib/abstract_controller/caching.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +66 -64
  8. data/lib/abstract_controller/collector.rb +6 -6
  9. data/lib/abstract_controller/deprecator.rb +2 -0
  10. data/lib/abstract_controller/error.rb +2 -0
  11. data/lib/abstract_controller/helpers.rb +70 -85
  12. data/lib/abstract_controller/logger.rb +2 -0
  13. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  14. data/lib/abstract_controller/rendering.rb +13 -12
  15. data/lib/abstract_controller/translation.rb +11 -10
  16. data/lib/abstract_controller/url_for.rb +8 -6
  17. data/lib/abstract_controller.rb +2 -0
  18. data/lib/action_controller/api/api_rendering.rb +2 -0
  19. data/lib/action_controller/api.rb +74 -72
  20. data/lib/action_controller/base.rb +155 -117
  21. data/lib/action_controller/caching.rb +15 -12
  22. data/lib/action_controller/deprecator.rb +2 -0
  23. data/lib/action_controller/form_builder.rb +20 -17
  24. data/lib/action_controller/log_subscriber.rb +3 -1
  25. data/lib/action_controller/metal/allow_browser.rb +119 -0
  26. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  27. data/lib/action_controller/metal/conditional_get.rb +188 -174
  28. data/lib/action_controller/metal/content_security_policy.rb +25 -24
  29. data/lib/action_controller/metal/cookies.rb +4 -2
  30. data/lib/action_controller/metal/data_streaming.rb +64 -55
  31. data/lib/action_controller/metal/default_headers.rb +5 -3
  32. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
  34. data/lib/action_controller/metal/exceptions.rb +11 -9
  35. data/lib/action_controller/metal/flash.rb +12 -10
  36. data/lib/action_controller/metal/head.rb +12 -10
  37. data/lib/action_controller/metal/helpers.rb +63 -55
  38. data/lib/action_controller/metal/http_authentication.rb +209 -201
  39. data/lib/action_controller/metal/implicit_render.rb +17 -15
  40. data/lib/action_controller/metal/instrumentation.rb +15 -12
  41. data/lib/action_controller/metal/live.rb +113 -107
  42. data/lib/action_controller/metal/logging.rb +6 -4
  43. data/lib/action_controller/metal/mime_responds.rb +151 -142
  44. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  45. data/lib/action_controller/metal/params_wrapper.rb +57 -59
  46. data/lib/action_controller/metal/permissions_policy.rb +13 -12
  47. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  48. data/lib/action_controller/metal/redirecting.rb +108 -82
  49. data/lib/action_controller/metal/renderers.rb +50 -49
  50. data/lib/action_controller/metal/rendering.rb +103 -75
  51. data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
  52. data/lib/action_controller/metal/rescue.rb +11 -9
  53. data/lib/action_controller/metal/streaming.rb +138 -136
  54. data/lib/action_controller/metal/strong_parameters.rb +525 -480
  55. data/lib/action_controller/metal/testing.rb +2 -0
  56. data/lib/action_controller/metal/url_for.rb +17 -15
  57. data/lib/action_controller/metal.rb +58 -57
  58. data/lib/action_controller/railtie.rb +3 -0
  59. data/lib/action_controller/railties/helpers.rb +2 -0
  60. data/lib/action_controller/renderer.rb +42 -36
  61. data/lib/action_controller/template_assertions.rb +4 -2
  62. data/lib/action_controller/test_case.rb +146 -126
  63. data/lib/action_controller.rb +10 -3
  64. data/lib/action_dispatch/constants.rb +2 -0
  65. data/lib/action_dispatch/deprecator.rb +2 -0
  66. data/lib/action_dispatch/http/cache.rb +27 -26
  67. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  68. data/lib/action_dispatch/http/content_security_policy.rb +44 -38
  69. data/lib/action_dispatch/http/filter_parameters.rb +9 -5
  70. data/lib/action_dispatch/http/filter_redirect.rb +15 -1
  71. data/lib/action_dispatch/http/headers.rb +22 -22
  72. data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
  73. data/lib/action_dispatch/http/mime_type.rb +29 -22
  74. data/lib/action_dispatch/http/mime_types.rb +2 -0
  75. data/lib/action_dispatch/http/parameters.rb +11 -9
  76. data/lib/action_dispatch/http/permissions_policy.rb +27 -37
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +71 -71
  79. data/lib/action_dispatch/http/response.rb +61 -61
  80. data/lib/action_dispatch/http/upload.rb +18 -16
  81. data/lib/action_dispatch/http/url.rb +75 -73
  82. data/lib/action_dispatch/journey/formatter.rb +13 -6
  83. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  84. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  85. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  86. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  87. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  88. data/lib/action_dispatch/journey/parser.rb +4 -3
  89. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  90. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  91. data/lib/action_dispatch/journey/route.rb +9 -7
  92. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  93. data/lib/action_dispatch/journey/router.rb +4 -2
  94. data/lib/action_dispatch/journey/routes.rb +4 -2
  95. data/lib/action_dispatch/journey/scanner.rb +4 -2
  96. data/lib/action_dispatch/journey/visitors.rb +2 -0
  97. data/lib/action_dispatch/journey.rb +2 -0
  98. data/lib/action_dispatch/log_subscriber.rb +2 -0
  99. data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
  100. data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
  101. data/lib/action_dispatch/middleware/callbacks.rb +3 -1
  102. data/lib/action_dispatch/middleware/cookies.rb +119 -104
  103. data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
  104. data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
  105. data/lib/action_dispatch/middleware/debug_view.rb +2 -0
  106. data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
  107. data/lib/action_dispatch/middleware/executor.rb +8 -0
  108. data/lib/action_dispatch/middleware/flash.rb +63 -51
  109. data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
  110. data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
  111. data/lib/action_dispatch/middleware/reloader.rb +5 -3
  112. data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
  113. data/lib/action_dispatch/middleware/request_id.rb +14 -9
  114. data/lib/action_dispatch/middleware/server_timing.rb +4 -2
  115. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
  116. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
  117. data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
  118. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
  119. data/lib/action_dispatch/middleware/show_exceptions.rb +31 -21
  120. data/lib/action_dispatch/middleware/ssl.rb +43 -40
  121. data/lib/action_dispatch/middleware/stack.rb +11 -10
  122. data/lib/action_dispatch/middleware/static.rb +33 -31
  123. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
  124. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -1
  125. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
  126. data/lib/action_dispatch/railtie.rb +2 -4
  127. data/lib/action_dispatch/request/session.rb +23 -21
  128. data/lib/action_dispatch/request/utils.rb +2 -0
  129. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  130. data/lib/action_dispatch/routing/inspector.rb +5 -3
  131. data/lib/action_dispatch/routing/mapper.rb +670 -635
  132. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  133. data/lib/action_dispatch/routing/redirection.rb +37 -32
  134. data/lib/action_dispatch/routing/route_set.rb +59 -45
  135. data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
  136. data/lib/action_dispatch/routing/url_for.rb +130 -125
  137. data/lib/action_dispatch/routing.rb +150 -148
  138. data/lib/action_dispatch/system_test_case.rb +91 -81
  139. data/lib/action_dispatch/system_testing/browser.rb +10 -3
  140. data/lib/action_dispatch/system_testing/driver.rb +3 -1
  141. data/lib/action_dispatch/system_testing/server.rb +2 -0
  142. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
  143. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  144. data/lib/action_dispatch/testing/assertion_response.rb +8 -6
  145. data/lib/action_dispatch/testing/assertions/response.rb +26 -23
  146. data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
  147. data/lib/action_dispatch/testing/assertions.rb +2 -0
  148. data/lib/action_dispatch/testing/integration.rb +223 -222
  149. data/lib/action_dispatch/testing/request_encoder.rb +2 -0
  150. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  151. data/lib/action_dispatch/testing/test_process.rb +12 -8
  152. data/lib/action_dispatch/testing/test_request.rb +3 -1
  153. data/lib/action_dispatch/testing/test_response.rb +27 -26
  154. data/lib/action_dispatch.rb +22 -28
  155. data/lib/action_pack/gem_version.rb +6 -4
  156. data/lib/action_pack/version.rb +3 -1
  157. data/lib/action_pack.rb +17 -16
  158. metadata +30 -13
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "abstract_controller/error"
4
6
  require "active_support/configurable"
5
7
  require "active_support/descendants_tracker"
@@ -26,12 +28,12 @@ module AbstractController
26
28
  end
27
29
  end
28
30
 
29
- # = Abstract Controller \Base
31
+ # # Abstract Controller Base
30
32
  #
31
- # AbstractController::Base is a low-level API. Nobody should be
32
- # using it directly, and subclasses (like ActionController::Base) are
33
- # expected to provide their own +render+ method, since rendering means
34
- # different things depending on the context.
33
+ # AbstractController::Base is a low-level API. Nobody should be using it
34
+ # directly, and subclasses (like ActionController::Base) are expected to provide
35
+ # their own `render` method, since rendering means different things depending on
36
+ # the context.
35
37
  class Base
36
38
  ##
37
39
  # Returns the body of the HTTP response sent by the controller.
@@ -52,27 +54,26 @@ module AbstractController
52
54
  attr_reader :abstract
53
55
  alias_method :abstract?, :abstract
54
56
 
55
- # Define a controller as abstract. See internal_methods for more
56
- # details.
57
+ # Define a controller as abstract. See internal_methods for more details.
57
58
  def abstract!
58
59
  @abstract = true
59
60
  end
60
61
 
61
62
  def inherited(klass) # :nodoc:
62
- # Define the abstract ivar on subclasses so that we don't get
63
- # uninitialized ivar warnings
63
+ # Define the abstract ivar on subclasses so that we don't get uninitialized ivar
64
+ # warnings
64
65
  unless klass.instance_variable_defined?(:@abstract)
65
66
  klass.instance_variable_set(:@abstract, false)
66
67
  end
67
68
  super
68
69
  end
69
70
 
70
- # A list of all internal methods for a controller. This finds the first
71
- # abstract superclass of a controller, and gets a list of all public
72
- # instance methods on that abstract class. Public instance methods of
73
- # a controller would normally be considered action methods, so methods
74
- # declared on abstract classes are being removed.
75
- # (ActionController::Metal and ActionController::Base are defined as abstract)
71
+ # A list of all internal methods for a controller. This finds the first abstract
72
+ # superclass of a controller, and gets a list of all public instance methods on
73
+ # that abstract class. Public instance methods of a controller would normally be
74
+ # considered action methods, so methods declared on abstract classes are being
75
+ # removed. (ActionController::Metal and ActionController::Base are defined as
76
+ # abstract)
76
77
  def internal_methods
77
78
  controller = self
78
79
  methods = []
@@ -85,18 +86,18 @@ module AbstractController
85
86
  controller.public_instance_methods(true) - methods
86
87
  end
87
88
 
88
- # A list of method names that should be considered actions. This
89
- # includes all public instance methods on a controller, less
90
- # any internal methods (see internal_methods), adding back in
91
- # any methods that are internal, but still exist on the class
92
- # itself.
89
+ # A list of method names that should be considered actions. This includes all
90
+ # public instance methods on a controller, less any internal methods (see
91
+ # internal_methods), adding back in any methods that are internal, but still
92
+ # exist on the class itself.
93
+ #
94
+ # #### Returns
95
+ # * `Set` - A set of all methods that should be considered actions.
93
96
  #
94
- # ==== Returns
95
- # * <tt>Set</tt> - A set of all methods that should be considered actions.
96
97
  def action_methods
97
98
  @action_methods ||= begin
98
- # All public instance methods of this class, including ancestors
99
- # except for public instance methods of Base and its ancestors.
99
+ # All public instance methods of this class, including ancestors except for
100
+ # public instance methods of Base and its ancestors.
100
101
  methods = public_instance_methods(true) - internal_methods
101
102
  # Be sure to include shadowed public instance methods of this class.
102
103
  methods.concat(public_instance_methods(false))
@@ -105,23 +106,24 @@ module AbstractController
105
106
  end
106
107
  end
107
108
 
108
- # action_methods are cached and there is sometimes a need to refresh
109
- # them. ::clear_action_methods! allows you to do that, so next time
110
- # you run action_methods, they will be recalculated.
109
+ # action_methods are cached and there is sometimes a need to refresh them.
110
+ # ::clear_action_methods! allows you to do that, so next time you run
111
+ # action_methods, they will be recalculated.
111
112
  def clear_action_methods!
112
113
  @action_methods = nil
113
114
  end
114
115
 
115
116
  # Returns the full controller name, underscored, without the ending Controller.
116
117
  #
117
- # class MyApp::MyPostsController < AbstractController::Base
118
+ # class MyApp::MyPostsController < AbstractController::Base
119
+ #
120
+ # end
118
121
  #
119
- # end
122
+ # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
120
123
  #
121
- # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
124
+ # #### Returns
125
+ # * `String`
122
126
  #
123
- # ==== Returns
124
- # * <tt>String</tt>
125
127
  def controller_path
126
128
  @controller_path ||= name.delete_suffix("Controller").underscore unless anonymous?
127
129
  end
@@ -142,13 +144,14 @@ module AbstractController
142
144
 
143
145
  # Calls the action going through the entire Action Dispatch stack.
144
146
  #
145
- # The actual method that is called is determined by calling
146
- # #method_for_action. If no method can handle the action, then an
147
- # AbstractController::ActionNotFound error is raised.
147
+ # The actual method that is called is determined by calling #method_for_action.
148
+ # If no method can handle the action, then an AbstractController::ActionNotFound
149
+ # error is raised.
148
150
  #
149
- # ==== Returns
150
- # * <tt>self</tt>
151
- def process(action, *args)
151
+ # #### Returns
152
+ # * `self`
153
+ #
154
+ def process(action, ...)
152
155
  @_action_name = action.to_s
153
156
 
154
157
  unless action_name = _find_action_name(@_action_name)
@@ -157,9 +160,8 @@ module AbstractController
157
160
 
158
161
  @_response_body = nil
159
162
 
160
- process_action(action_name, *args)
163
+ process_action(action_name, ...)
161
164
  end
162
- ruby2_keywords(:process)
163
165
 
164
166
  # Delegates to the class's ::controller_path.
165
167
  def controller_path
@@ -171,31 +173,30 @@ module AbstractController
171
173
  self.class.action_methods
172
174
  end
173
175
 
174
- # Returns true if a method for the action is available and
175
- # can be dispatched, false otherwise.
176
+ # Returns true if a method for the action is available and can be dispatched,
177
+ # false otherwise.
178
+ #
179
+ # Notice that `action_methods.include?("foo")` may return false and
180
+ # `available_action?("foo")` returns true because this method considers actions
181
+ # that are also available through other means, for example, implicit render
182
+ # ones.
176
183
  #
177
- # Notice that <tt>action_methods.include?("foo")</tt> may return
178
- # false and <tt>available_action?("foo")</tt> returns true because
179
- # this method considers actions that are also available
180
- # through other means, for example, implicit render ones.
184
+ # #### Parameters
185
+ # * `action_name` - The name of an action to be tested
181
186
  #
182
- # ==== Parameters
183
- # * <tt>action_name</tt> - The name of an action to be tested
184
187
  def available_action?(action_name)
185
188
  _find_action_name(action_name)
186
189
  end
187
190
 
188
- # Tests if a response body is set. Used to determine if the
189
- # +process_action+ callback needs to be terminated in
190
- # AbstractController::Callbacks.
191
+ # Tests if a response body is set. Used to determine if the `process_action`
192
+ # callback needs to be terminated in AbstractController::Callbacks.
191
193
  def performed?
192
194
  response_body
193
195
  end
194
196
 
195
- # Returns true if the given controller is capable of rendering
196
- # a path. A subclass of +AbstractController::Base+
197
- # may return false. An Email controller for example does not
198
- # support paths, only full URLs.
197
+ # Returns true if the given controller is capable of rendering a path. A
198
+ # subclass of `AbstractController::Base` may return false. An Email controller
199
+ # for example does not support paths, only full URLs.
199
200
  def self.supports_path?
200
201
  true
201
202
  end
@@ -205,80 +206,83 @@ module AbstractController
205
206
  end
206
207
 
207
208
  private
208
- # Returns true if the name can be considered an action because
209
- # it has a method defined in the controller.
209
+ # Returns true if the name can be considered an action because it has a method
210
+ # defined in the controller.
211
+ #
212
+ # #### Parameters
213
+ # * `name` - The name of an action to be tested
210
214
  #
211
- # ==== Parameters
212
- # * <tt>name</tt> - The name of an action to be tested
213
215
  def action_method?(name)
214
216
  self.class.action_methods.include?(name)
215
217
  end
216
218
 
217
- # Call the action. Override this in a subclass to modify the
218
- # behavior around processing an action. This, and not #process,
219
- # is the intended way to override action dispatching.
219
+ # Call the action. Override this in a subclass to modify the behavior around
220
+ # processing an action. This, and not #process, is the intended way to override
221
+ # action dispatching.
220
222
  #
221
- # Notice that the first argument is the method to be dispatched
222
- # which is *not* necessarily the same as the action name.
223
+ # Notice that the first argument is the method to be dispatched which is **not**
224
+ # necessarily the same as the action name.
223
225
  def process_action(...)
224
226
  send_action(...)
225
227
  end
226
228
 
227
- # Actually call the method associated with the action. Override
228
- # this method if you wish to change how action methods are called,
229
- # not to add additional behavior around it. For example, you would
230
- # override #send_action if you want to inject arguments into the
231
- # method.
229
+ # Actually call the method associated with the action. Override this method if
230
+ # you wish to change how action methods are called, not to add additional
231
+ # behavior around it. For example, you would override #send_action if you want
232
+ # to inject arguments into the method.
232
233
  alias send_action send
233
234
 
234
- # If the action name was not found, but a method called "action_missing"
235
- # was found, #method_for_action will return "_handle_action_missing".
236
- # This method calls #action_missing with the current action name.
235
+ # If the action name was not found, but a method called "action_missing" was
236
+ # found, #method_for_action will return "_handle_action_missing". This method
237
+ # calls #action_missing with the current action name.
237
238
  def _handle_action_missing(*args)
238
239
  action_missing(@_action_name, *args)
239
240
  end
240
241
 
241
- # Takes an action name and returns the name of the method that will
242
- # handle the action.
242
+ # Takes an action name and returns the name of the method that will handle the
243
+ # action.
243
244
  #
244
245
  # It checks if the action name is valid and returns false otherwise.
245
246
  #
246
247
  # See method_for_action for more information.
247
248
  #
248
- # ==== Parameters
249
- # * <tt>action_name</tt> - An action name to find a method name for
249
+ # #### Parameters
250
+ # * `action_name` - An action name to find a method name for
251
+ #
252
+ #
253
+ # #### Returns
254
+ # * `string` - The name of the method that handles the action
255
+ # * false - No valid method name could be found.
250
256
  #
251
- # ==== Returns
252
- # * <tt>string</tt> - The name of the method that handles the action
253
- # * false - No valid method name could be found.
254
- # Raise +AbstractController::ActionNotFound+.
257
+ # Raise `AbstractController::ActionNotFound`.
255
258
  def _find_action_name(action_name)
256
259
  _valid_action_name?(action_name) && method_for_action(action_name)
257
260
  end
258
261
 
259
- # Takes an action name and returns the name of the method that will
260
- # handle the action. In normal cases, this method returns the same
261
- # name as it receives. By default, if #method_for_action receives
262
- # a name that is not an action, it will look for an #action_missing
263
- # method and return "_handle_action_missing" if one is found.
262
+ # Takes an action name and returns the name of the method that will handle the
263
+ # action. In normal cases, this method returns the same name as it receives. By
264
+ # default, if #method_for_action receives a name that is not an action, it will
265
+ # look for an #action_missing method and return "_handle_action_missing" if one
266
+ # is found.
267
+ #
268
+ # Subclasses may override this method to add additional conditions that should
269
+ # be considered an action. For instance, an HTTP controller with a template
270
+ # matching the action name is considered to exist.
271
+ #
272
+ # If you override this method to handle additional cases, you may also provide a
273
+ # method (like `_handle_method_missing`) to handle the case.
264
274
  #
265
- # Subclasses may override this method to add additional conditions
266
- # that should be considered an action. For instance, an HTTP controller
267
- # with a template matching the action name is considered to exist.
275
+ # If none of these conditions are true, and `method_for_action` returns `nil`,
276
+ # an `AbstractController::ActionNotFound` exception will be raised.
268
277
  #
269
- # If you override this method to handle additional cases, you may
270
- # also provide a method (like +_handle_method_missing+) to handle
271
- # the case.
278
+ # #### Parameters
279
+ # * `action_name` - An action name to find a method name for
272
280
  #
273
- # If none of these conditions are true, and +method_for_action+
274
- # returns +nil+, an +AbstractController::ActionNotFound+ exception will be raised.
275
281
  #
276
- # ==== Parameters
277
- # * <tt>action_name</tt> - An action name to find a method name for
282
+ # #### Returns
283
+ # * `string` - The name of the method that handles the action
284
+ # * `nil` - No method name could be found.
278
285
  #
279
- # ==== Returns
280
- # * <tt>string</tt> - The name of the method that handles the action
281
- # * <tt>nil</tt> - No method name could be found.
282
286
  def method_for_action(action_name)
283
287
  if action_method?(action_name)
284
288
  action_name
@@ -1,22 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module AbstractController
4
6
  module Caching
5
- # = Abstract Controller Caching \Fragments
7
+ # # Abstract Controller Caching Fragments
6
8
  #
7
- # Fragment caching is used for caching various blocks within
8
- # views without caching the entire action as a whole. This is
9
- # useful when certain elements of an action change frequently or
10
- # depend on complicated state while other parts rarely change or
11
- # can be shared amongst multiple parties. The caching is done using
12
- # the +cache+ helper available in the Action View. See
9
+ # Fragment caching is used for caching various blocks within views without
10
+ # caching the entire action as a whole. This is useful when certain elements of
11
+ # an action change frequently or depend on complicated state while other parts
12
+ # rarely change or can be shared amongst multiple parties. The caching is done
13
+ # using the `cache` helper available in the Action View. See
13
14
  # ActionView::Helpers::CacheHelper for more information.
14
15
  #
15
- # While it's strongly recommended that you use key-based cache
16
- # expiration (see links in CacheHelper for more information),
17
- # it is also possible to manually expire caches. For example:
16
+ # While it's strongly recommended that you use key-based cache expiration (see
17
+ # links in CacheHelper for more information), it is also possible to manually
18
+ # expire caches. For example:
18
19
  #
19
- # expire_fragment('name_of_cache')
20
+ # expire_fragment('name_of_cache')
20
21
  module Fragments
21
22
  extend ActiveSupport::Concern
22
23
 
@@ -35,38 +36,35 @@ module AbstractController
35
36
  end
36
37
 
37
38
  module ClassMethods
38
- # Allows you to specify controller-wide key prefixes for
39
- # cache fragments. Pass either a constant +value+, or a block
40
- # which computes a value each time a cache key is generated.
39
+ # Allows you to specify controller-wide key prefixes for cache fragments. Pass
40
+ # either a constant `value`, or a block which computes a value each time a cache
41
+ # key is generated.
41
42
  #
42
- # For example, you may want to prefix all fragment cache keys
43
- # with a global version identifier, so you can easily
44
- # invalidate all caches.
43
+ # For example, you may want to prefix all fragment cache keys with a global
44
+ # version identifier, so you can easily invalidate all caches.
45
45
  #
46
- # class ApplicationController
47
- # fragment_cache_key "v1"
48
- # end
46
+ # class ApplicationController
47
+ # fragment_cache_key "v1"
48
+ # end
49
49
  #
50
- # When it's time to invalidate all fragments, simply change
51
- # the string constant. Or, progressively roll out the cache
52
- # invalidation using a computed value:
50
+ # When it's time to invalidate all fragments, simply change the string constant.
51
+ # Or, progressively roll out the cache invalidation using a computed value:
53
52
  #
54
- # class ApplicationController
55
- # fragment_cache_key do
56
- # @account.id.odd? ? "v1" : "v2"
53
+ # class ApplicationController
54
+ # fragment_cache_key do
55
+ # @account.id.odd? ? "v1" : "v2"
56
+ # end
57
57
  # end
58
- # end
59
58
  def fragment_cache_key(value = nil, &key)
60
59
  self.fragment_cache_keys += [key || -> { value }]
61
60
  end
62
61
  end
63
62
 
64
- # Given a key (as described in +expire_fragment+), returns
65
- # a key array suitable for use in reading, writing, or expiring a
66
- # cached fragment. All keys begin with <tt>:views</tt>,
67
- # followed by <tt>ENV["RAILS_CACHE_ID"]</tt> or <tt>ENV["RAILS_APP_VERSION"]</tt> if set,
68
- # followed by any controller-wide key prefix values, ending
69
- # with the specified +key+ value.
63
+ # Given a key (as described in `expire_fragment`), returns a key array suitable
64
+ # for use in reading, writing, or expiring a cached fragment. All keys begin
65
+ # with `:views`, followed by `ENV["RAILS_CACHE_ID"]` or
66
+ # `ENV["RAILS_APP_VERSION"]` if set, followed by any controller-wide key prefix
67
+ # values, ending with the specified `key` value.
70
68
  def combined_fragment_cache_key(key)
71
69
  head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
72
70
  tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
@@ -77,8 +75,8 @@ module AbstractController
77
75
  cache_key
78
76
  end
79
77
 
80
- # Writes +content+ to the location signified by
81
- # +key+ (see +expire_fragment+ for acceptable formats).
78
+ # Writes `content` to the location signified by `key` (see `expire_fragment` for
79
+ # acceptable formats).
82
80
  def write_fragment(key, content, options = nil)
83
81
  return content unless cache_configured?
84
82
 
@@ -90,8 +88,8 @@ module AbstractController
90
88
  content
91
89
  end
92
90
 
93
- # Reads a cached fragment from the location signified by +key+
94
- # (see +expire_fragment+ for acceptable formats).
91
+ # Reads a cached fragment from the location signified by `key` (see
92
+ # `expire_fragment` for acceptable formats).
95
93
  def read_fragment(key, options = nil)
96
94
  return unless cache_configured?
97
95
 
@@ -102,8 +100,8 @@ module AbstractController
102
100
  end
103
101
  end
104
102
 
105
- # Check if a cached fragment from the location signified by
106
- # +key+ exists (see +expire_fragment+ for acceptable formats).
103
+ # Check if a cached fragment from the location signified by `key` exists (see
104
+ # `expire_fragment` for acceptable formats).
107
105
  def fragment_exist?(key, options = nil)
108
106
  return unless cache_configured?
109
107
  key = combined_fragment_cache_key(key)
@@ -115,22 +113,21 @@ module AbstractController
115
113
 
116
114
  # Removes fragments from the cache.
117
115
  #
118
- # +key+ can take one of three forms:
116
+ # `key` can take one of three forms:
117
+ #
118
+ # * String - This would normally take the form of a path, like
119
+ # `pages/45/notes`.
120
+ # * Hash - Treated as an implicit call to `url_for`, like `{ controller:
121
+ # 'pages', action: 'notes', id: 45}`
122
+ # * Regexp - Will remove any fragment that matches, so `%r{pages/\d*/notes}`
123
+ # might remove all notes. Make sure you don't use anchors in the regex (`^`
124
+ # or `$`) because the actual filename matched looks like
125
+ # `./cache/filename/path.cache`. Note: Regexp expiration is only supported
126
+ # on caches that can iterate over all keys (unlike memcached).
119
127
  #
120
- # * String - This would normally take the form of a path, like
121
- # <tt>pages/45/notes</tt>.
122
- # * Hash - Treated as an implicit call to +url_for+, like
123
- # <tt>{ controller: 'pages', action: 'notes', id: 45}</tt>
124
- # * Regexp - Will remove any fragment that matches, so
125
- # <tt>%r{pages/\d*/notes}</tt> might remove all notes. Make sure you
126
- # don't use anchors in the regex (<tt>^</tt> or <tt>$</tt>) because
127
- # the actual filename matched looks like
128
- # <tt>./cache/filename/path.cache</tt>. Note: Regexp expiration is
129
- # only supported on caches that can iterate over all keys (unlike
130
- # memcached).
131
128
  #
132
- # +options+ is passed through to the cache store's +delete+
133
- # method (or <tt>delete_matched</tt>, for Regexp keys).
129
+ # `options` is passed through to the cache store's `delete` method (or
130
+ # `delete_matched`, for Regexp keys).
134
131
  def expire_fragment(key, options = nil)
135
132
  return unless cache_configured?
136
133
  key = combined_fragment_cache_key(key) unless key.is_a?(Regexp)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module AbstractController
4
6
  module Caching
5
7
  extend ActiveSupport::Concern