actionpack 7.1.6 → 7.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +117 -607
  3. data/README.rdoc +1 -1
  4. data/lib/abstract_controller/asset_paths.rb +2 -0
  5. data/lib/abstract_controller/base.rb +93 -100
  6. data/lib/abstract_controller/caching/fragments.rb +50 -53
  7. data/lib/abstract_controller/caching.rb +2 -0
  8. data/lib/abstract_controller/callbacks.rb +66 -64
  9. data/lib/abstract_controller/collector.rb +7 -7
  10. data/lib/abstract_controller/deprecator.rb +2 -0
  11. data/lib/abstract_controller/error.rb +2 -0
  12. data/lib/abstract_controller/helpers.rb +71 -84
  13. data/lib/abstract_controller/logger.rb +2 -0
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/rendering.rb +13 -12
  16. data/lib/abstract_controller/translation.rb +12 -13
  17. data/lib/abstract_controller/url_for.rb +8 -6
  18. data/lib/abstract_controller.rb +2 -0
  19. data/lib/action_controller/api/api_rendering.rb +2 -0
  20. data/lib/action_controller/api.rb +75 -72
  21. data/lib/action_controller/base.rb +198 -126
  22. data/lib/action_controller/caching.rb +15 -12
  23. data/lib/action_controller/deprecator.rb +2 -0
  24. data/lib/action_controller/form_builder.rb +20 -17
  25. data/lib/action_controller/log_subscriber.rb +3 -1
  26. data/lib/action_controller/metal/allow_browser.rb +123 -0
  27. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  28. data/lib/action_controller/metal/conditional_get.rb +187 -174
  29. data/lib/action_controller/metal/content_security_policy.rb +25 -24
  30. data/lib/action_controller/metal/cookies.rb +4 -2
  31. data/lib/action_controller/metal/data_streaming.rb +69 -62
  32. data/lib/action_controller/metal/default_headers.rb +5 -3
  33. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  34. data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
  35. data/lib/action_controller/metal/exceptions.rb +11 -9
  36. data/lib/action_controller/metal/flash.rb +12 -10
  37. data/lib/action_controller/metal/head.rb +12 -10
  38. data/lib/action_controller/metal/helpers.rb +63 -55
  39. data/lib/action_controller/metal/http_authentication.rb +209 -201
  40. data/lib/action_controller/metal/implicit_render.rb +17 -15
  41. data/lib/action_controller/metal/instrumentation.rb +15 -12
  42. data/lib/action_controller/metal/live.rb +116 -108
  43. data/lib/action_controller/metal/logging.rb +6 -4
  44. data/lib/action_controller/metal/mime_responds.rb +151 -142
  45. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  46. data/lib/action_controller/metal/params_wrapper.rb +57 -59
  47. data/lib/action_controller/metal/permissions_policy.rb +13 -12
  48. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  49. data/lib/action_controller/metal/redirecting.rb +112 -85
  50. data/lib/action_controller/metal/renderers.rb +50 -49
  51. data/lib/action_controller/metal/rendering.rb +104 -76
  52. data/lib/action_controller/metal/request_forgery_protection.rb +165 -134
  53. data/lib/action_controller/metal/rescue.rb +11 -9
  54. data/lib/action_controller/metal/streaming.rb +138 -136
  55. data/lib/action_controller/metal/strong_parameters.rb +483 -481
  56. data/lib/action_controller/metal/testing.rb +2 -0
  57. data/lib/action_controller/metal/url_for.rb +17 -15
  58. data/lib/action_controller/metal.rb +86 -60
  59. data/lib/action_controller/railtie.rb +3 -0
  60. data/lib/action_controller/railties/helpers.rb +2 -0
  61. data/lib/action_controller/renderer.rb +41 -36
  62. data/lib/action_controller/template_assertions.rb +4 -2
  63. data/lib/action_controller/test_case.rb +148 -129
  64. data/lib/action_controller.rb +5 -1
  65. data/lib/action_dispatch/constants.rb +8 -0
  66. data/lib/action_dispatch/deprecator.rb +2 -0
  67. data/lib/action_dispatch/http/cache.rb +27 -26
  68. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  69. data/lib/action_dispatch/http/content_security_policy.rb +40 -38
  70. data/lib/action_dispatch/http/filter_parameters.rb +9 -5
  71. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  72. data/lib/action_dispatch/http/headers.rb +22 -22
  73. data/lib/action_dispatch/http/mime_negotiation.rb +35 -41
  74. data/lib/action_dispatch/http/mime_type.rb +25 -21
  75. data/lib/action_dispatch/http/mime_types.rb +2 -0
  76. data/lib/action_dispatch/http/parameters.rb +11 -9
  77. data/lib/action_dispatch/http/permissions_policy.rb +19 -36
  78. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  79. data/lib/action_dispatch/http/request.rb +72 -72
  80. data/lib/action_dispatch/http/response.rb +88 -62
  81. data/lib/action_dispatch/http/upload.rb +18 -16
  82. data/lib/action_dispatch/http/url.rb +77 -75
  83. data/lib/action_dispatch/journey/formatter.rb +21 -9
  84. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  85. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  86. data/lib/action_dispatch/journey/gtg/transition_table.rb +14 -12
  87. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  88. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  89. data/lib/action_dispatch/journey/parser.rb +4 -3
  90. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  91. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  92. data/lib/action_dispatch/journey/route.rb +9 -7
  93. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  94. data/lib/action_dispatch/journey/router.rb +4 -2
  95. data/lib/action_dispatch/journey/routes.rb +4 -2
  96. data/lib/action_dispatch/journey/scanner.rb +4 -2
  97. data/lib/action_dispatch/journey/visitors.rb +2 -0
  98. data/lib/action_dispatch/journey.rb +2 -0
  99. data/lib/action_dispatch/log_subscriber.rb +2 -0
  100. data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
  101. data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
  102. data/lib/action_dispatch/middleware/callbacks.rb +3 -1
  103. data/lib/action_dispatch/middleware/cookies.rb +119 -104
  104. data/lib/action_dispatch/middleware/debug_exceptions.rb +16 -6
  105. data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
  106. data/lib/action_dispatch/middleware/debug_view.rb +2 -0
  107. data/lib/action_dispatch/middleware/exception_wrapper.rb +9 -14
  108. data/lib/action_dispatch/middleware/executor.rb +7 -2
  109. data/lib/action_dispatch/middleware/flash.rb +63 -51
  110. data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
  111. data/lib/action_dispatch/middleware/public_exceptions.rb +13 -7
  112. data/lib/action_dispatch/middleware/reloader.rb +5 -3
  113. data/lib/action_dispatch/middleware/remote_ip.rb +76 -72
  114. data/lib/action_dispatch/middleware/request_id.rb +14 -9
  115. data/lib/action_dispatch/middleware/server_timing.rb +4 -2
  116. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
  117. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
  118. data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
  119. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
  120. data/lib/action_dispatch/middleware/show_exceptions.rb +16 -16
  121. data/lib/action_dispatch/middleware/ssl.rb +43 -40
  122. data/lib/action_dispatch/middleware/stack.rb +11 -10
  123. data/lib/action_dispatch/middleware/static.rb +33 -31
  124. data/lib/action_dispatch/middleware/templates/rescues/_source.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 -3
  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 +622 -623
  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 +4 -2
  140. data/lib/action_dispatch/system_testing/driver.rb +2 -0
  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 +9 -7
  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 +222 -222
  149. data/lib/action_dispatch/testing/request_encoder.rb +11 -9
  150. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  151. data/lib/action_dispatch/testing/test_process.rb +11 -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 +5 -3
  156. data/lib/action_pack/version.rb +3 -1
  157. data/lib/action_pack.rb +17 -16
  158. metadata +34 -11
data/README.rdoc CHANGED
@@ -52,6 +52,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
52
52
 
53
53
  * https://github.com/rails/rails/issues
54
54
 
55
- Feature requests should be discussed on the rails-core mailing list here:
55
+ Feature requests should be discussed on the rubyonrails-core forum here:
56
56
 
57
57
  * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module AbstractController
4
6
  module AssetPaths # :nodoc:
5
7
  extend ActiveSupport::Concern
@@ -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,14 @@ 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.
93
- #
94
- # ==== Returns
95
- # * <tt>Set</tt> - A set of all methods that should be considered actions.
89
+ # A `Set` 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.
96
93
  def action_methods
97
94
  @action_methods ||= begin
98
- # All public instance methods of this class, including ancestors
99
- # except for public instance methods of Base and its ancestors.
95
+ # All public instance methods of this class, including ancestors except for
96
+ # public instance methods of Base and its ancestors.
100
97
  methods = public_instance_methods(true) - internal_methods
101
98
  # Be sure to include shadowed public instance methods of this class.
102
99
  methods.concat(public_instance_methods(false))
@@ -105,23 +102,21 @@ module AbstractController
105
102
  end
106
103
  end
107
104
 
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.
105
+ # action_methods are cached and there is sometimes a need to refresh them.
106
+ # ::clear_action_methods! allows you to do that, so next time you run
107
+ # action_methods, they will be recalculated.
111
108
  def clear_action_methods!
112
109
  @action_methods = nil
113
110
  end
114
111
 
115
112
  # Returns the full controller name, underscored, without the ending Controller.
116
113
  #
117
- # class MyApp::MyPostsController < AbstractController::Base
114
+ # class MyApp::MyPostsController < AbstractController::Base
118
115
  #
119
- # end
116
+ # end
120
117
  #
121
- # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
118
+ # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
122
119
  #
123
- # ==== Returns
124
- # * <tt>String</tt>
125
120
  def controller_path
126
121
  @controller_path ||= name.delete_suffix("Controller").underscore unless anonymous?
127
122
  end
@@ -142,13 +137,10 @@ module AbstractController
142
137
 
143
138
  # Calls the action going through the entire Action Dispatch stack.
144
139
  #
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.
148
- #
149
- # ==== Returns
150
- # * <tt>self</tt>
151
- def process(action, *args)
140
+ # The actual method that is called is determined by calling #method_for_action.
141
+ # If no method can handle the action, then an AbstractController::ActionNotFound
142
+ # error is raised.
143
+ def process(action, ...)
152
144
  @_action_name = action.to_s
153
145
 
154
146
  unless action_name = _find_action_name(@_action_name)
@@ -157,9 +149,8 @@ module AbstractController
157
149
 
158
150
  @_response_body = nil
159
151
 
160
- process_action(action_name, *args)
152
+ process_action(action_name, ...)
161
153
  end
162
- ruby2_keywords(:process)
163
154
 
164
155
  # Delegates to the class's ::controller_path.
165
156
  def controller_path
@@ -171,31 +162,30 @@ module AbstractController
171
162
  self.class.action_methods
172
163
  end
173
164
 
174
- # Returns true if a method for the action is available and
175
- # can be dispatched, false otherwise.
165
+ # Returns true if a method for the action is available and can be dispatched,
166
+ # false otherwise.
176
167
  #
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.
168
+ # Notice that `action_methods.include?("foo")` may return false and
169
+ # `available_action?("foo")` returns true because this method considers actions
170
+ # that are also available through other means, for example, implicit render
171
+ # ones.
172
+ #
173
+ # #### Parameters
174
+ # * `action_name` - The name of an action to be tested
181
175
  #
182
- # ==== Parameters
183
- # * <tt>action_name</tt> - The name of an action to be tested
184
176
  def available_action?(action_name)
185
177
  _find_action_name(action_name)
186
178
  end
187
179
 
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.
180
+ # Tests if a response body is set. Used to determine if the `process_action`
181
+ # callback needs to be terminated in AbstractController::Callbacks.
191
182
  def performed?
192
183
  response_body
193
184
  end
194
185
 
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.
186
+ # Returns true if the given controller is capable of rendering a path. A
187
+ # subclass of `AbstractController::Base` may return false. An Email controller
188
+ # for example does not support paths, only full URLs.
199
189
  def self.supports_path?
200
190
  true
201
191
  end
@@ -205,80 +195,83 @@ module AbstractController
205
195
  end
206
196
 
207
197
  private
208
- # Returns true if the name can be considered an action because
209
- # it has a method defined in the controller.
198
+ # Returns true if the name can be considered an action because it has a method
199
+ # defined in the controller.
200
+ #
201
+ # #### Parameters
202
+ # * `name` - The name of an action to be tested
210
203
  #
211
- # ==== Parameters
212
- # * <tt>name</tt> - The name of an action to be tested
213
204
  def action_method?(name)
214
205
  self.class.action_methods.include?(name)
215
206
  end
216
207
 
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.
208
+ # Call the action. Override this in a subclass to modify the behavior around
209
+ # processing an action. This, and not #process, is the intended way to override
210
+ # action dispatching.
220
211
  #
221
- # Notice that the first argument is the method to be dispatched
222
- # which is *not* necessarily the same as the action name.
212
+ # Notice that the first argument is the method to be dispatched which is **not**
213
+ # necessarily the same as the action name.
223
214
  def process_action(...)
224
215
  send_action(...)
225
216
  end
226
217
 
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.
218
+ # Actually call the method associated with the action. Override this method if
219
+ # you wish to change how action methods are called, not to add additional
220
+ # behavior around it. For example, you would override #send_action if you want
221
+ # to inject arguments into the method.
232
222
  alias send_action send
233
223
 
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.
224
+ # If the action name was not found, but a method called "action_missing" was
225
+ # found, #method_for_action will return "_handle_action_missing". This method
226
+ # calls #action_missing with the current action name.
237
227
  def _handle_action_missing(*args)
238
228
  action_missing(@_action_name, *args)
239
229
  end
240
230
 
241
- # Takes an action name and returns the name of the method that will
242
- # handle the action.
231
+ # Takes an action name and returns the name of the method that will handle the
232
+ # action.
243
233
  #
244
234
  # It checks if the action name is valid and returns false otherwise.
245
235
  #
246
236
  # See method_for_action for more information.
247
237
  #
248
- # ==== Parameters
249
- # * <tt>action_name</tt> - An action name to find a method name for
238
+ # #### Parameters
239
+ # * `action_name` - An action name to find a method name for
250
240
  #
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+.
241
+ #
242
+ # #### Returns
243
+ # * `string` - The name of the method that handles the action
244
+ # * false - No valid method name could be found.
245
+ #
246
+ # Raise `AbstractController::ActionNotFound`.
255
247
  def _find_action_name(action_name)
256
248
  _valid_action_name?(action_name) && method_for_action(action_name)
257
249
  end
258
250
 
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.
251
+ # Takes an action name and returns the name of the method that will handle the
252
+ # action. In normal cases, this method returns the same name as it receives. By
253
+ # default, if #method_for_action receives a name that is not an action, it will
254
+ # look for an #action_missing method and return "_handle_action_missing" if one
255
+ # is found.
256
+ #
257
+ # Subclasses may override this method to add additional conditions that should
258
+ # be considered an action. For instance, an HTTP controller with a template
259
+ # matching the action name is considered to exist.
260
+ #
261
+ # If you override this method to handle additional cases, you may also provide a
262
+ # method (like `_handle_method_missing`) to handle the case.
264
263
  #
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.
264
+ # If none of these conditions are true, and `method_for_action` returns `nil`,
265
+ # an `AbstractController::ActionNotFound` exception will be raised.
268
266
  #
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.
267
+ # #### Parameters
268
+ # * `action_name` - An action name to find a method name for
272
269
  #
273
- # If none of these conditions are true, and +method_for_action+
274
- # returns +nil+, an +AbstractController::ActionNotFound+ exception will be raised.
275
270
  #
276
- # ==== Parameters
277
- # * <tt>action_name</tt> - An action name to find a method name for
271
+ # #### Returns
272
+ # * `string` - The name of the method that handles the action
273
+ # * `nil` - No method name could be found.
278
274
  #
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
275
  def method_for_action(action_name)
283
276
  if action_method?(action_name)
284
277
  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