actionpack 7.1.3 → 7.2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -501
  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 +15 -7
  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 +198 -126
  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 +123 -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 +210 -205
  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 +86 -60
  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 +18 -9
  70. data/lib/action_dispatch/http/filter_redirect.rb +22 -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 +31 -24
  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 +20 -44
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +94 -75
  79. data/lib/action_dispatch/http/response.rb +73 -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 +671 -636
  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 +39 -16
@@ -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,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