actionpack 7.0.8.1 → 7.2.2.1

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