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
@@ -1,46 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module AbstractController
4
- # = Abstract Controller Callbacks
5
- #
6
- # Abstract Controller provides hooks during the life cycle of a controller action.
7
- # Callbacks allow you to trigger logic during this cycle. Available callbacks are:
6
+ # # Abstract Controller Callbacks
8
7
  #
9
- # * <tt>after_action</tt>
10
- # * <tt>append_after_action</tt>
11
- # * <tt>append_around_action</tt>
12
- # * <tt>append_before_action</tt>
13
- # * <tt>around_action</tt>
14
- # * <tt>before_action</tt>
15
- # * <tt>prepend_after_action</tt>
16
- # * <tt>prepend_around_action</tt>
17
- # * <tt>prepend_before_action</tt>
18
- # * <tt>skip_after_action</tt>
19
- # * <tt>skip_around_action</tt>
20
- # * <tt>skip_before_action</tt>
21
- #
22
- # NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
8
+ # Abstract Controller provides hooks during the life cycle of a controller
9
+ # action. Callbacks allow you to trigger logic during this cycle. Available
10
+ # callbacks are:
23
11
  #
12
+ # * `after_action`
13
+ # * `append_after_action`
14
+ # * `append_around_action`
15
+ # * `append_before_action`
16
+ # * `around_action`
17
+ # * `before_action`
18
+ # * `prepend_after_action`
19
+ # * `prepend_around_action`
20
+ # * `prepend_before_action`
21
+ # * `skip_after_action`
22
+ # * `skip_around_action`
23
+ # * `skip_before_action`
24
24
  module Callbacks
25
25
  extend ActiveSupport::Concern
26
26
 
27
- # Uses ActiveSupport::Callbacks as the base functionality. For
28
- # more details on the whole callback system, read the documentation
29
- # for ActiveSupport::Callbacks.
27
+ # Uses ActiveSupport::Callbacks as the base functionality. For more details on
28
+ # the whole callback system, read the documentation for
29
+ # ActiveSupport::Callbacks.
30
30
  include ActiveSupport::Callbacks
31
31
 
32
32
  included do
33
33
  define_callbacks :process_action,
34
34
  terminator: ->(controller, result_lambda) { result_lambda.call; controller.performed? },
35
35
  skip_after_callbacks_if_terminated: true
36
+ mattr_accessor :raise_on_missing_callback_actions, default: false
36
37
  end
37
38
 
38
39
  class ActionFilter # :nodoc:
39
- def initialize(actions)
40
+ def initialize(filters, conditional_key, actions)
41
+ @filters = filters.to_a
42
+ @conditional_key = conditional_key
40
43
  @actions = Array(actions).map(&:to_s).to_set
41
44
  end
42
45
 
43
46
  def match?(controller)
47
+ if controller.raise_on_missing_callback_actions
48
+ missing_action = @actions.find { |action| !controller.available_action?(action) }
49
+ if missing_action
50
+ filter_names = @filters.length == 1 ? @filters.first.inspect : @filters.inspect
51
+
52
+ message = <<~MSG
53
+ The #{missing_action} action could not be found for the #{filter_names}
54
+ callback on #{controller.class.name}, but it is listed in the controller's
55
+ #{@conditional_key.inspect} option.
56
+
57
+ Raising for missing callback actions is a new default in Rails 7.1, if you'd
58
+ like to turn this off you can delete the option from the environment configurations
59
+ or set `config.action_controller.raise_on_missing_callback_actions` to `false`.
60
+ MSG
61
+
62
+ raise ActionNotFound.new(message, controller, missing_action)
63
+ end
64
+ end
65
+
44
66
  @actions.include?(controller.action_name)
45
67
  end
46
68
 
@@ -50,53 +72,57 @@ module AbstractController
50
72
  end
51
73
 
52
74
  module ClassMethods
53
- # If +:only+ or +:except+ are used, convert the options into the
54
- # +:if+ and +:unless+ options of ActiveSupport::Callbacks.
75
+ # If `:only` or `:except` are used, convert the options into the `:if` and
76
+ # `:unless` options of ActiveSupport::Callbacks.
77
+ #
78
+ # The basic idea is that `:only => :index` gets converted to `:if => proc {|c|
79
+ # c.action_name == "index" }`.
55
80
  #
56
- # The basic idea is that <tt>:only => :index</tt> gets converted to
57
- # <tt>:if => proc {|c| c.action_name == "index" }</tt>.
81
+ # Note that `:only` has priority over `:if` in case they are used together.
58
82
  #
59
- # Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they
60
- # are used together.
83
+ # only: :index, if: -> { true } # the :if option will be ignored.
61
84
  #
62
- # only: :index, if: -> { true } # the :if option will be ignored.
85
+ # Note that `:if` has priority over `:except` in case they are used together.
63
86
  #
64
- # Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they
65
- # are used together.
87
+ # except: :index, if: -> { true } # the :except option will be ignored.
66
88
  #
67
- # except: :index, if: -> { true } # the :except option will be ignored.
89
+ # #### Options
90
+ # * `only` - The callback should be run only for this action.
91
+ # * `except` - The callback should be run for all actions except this action.
68
92
  #
69
- # ==== Options
70
- # * <tt>only</tt> - The callback should be run only for this action.
71
- # * <tt>except</tt> - The callback should be run for all actions except this action.
72
93
  def _normalize_callback_options(options)
73
94
  _normalize_callback_option(options, :only, :if)
74
95
  _normalize_callback_option(options, :except, :unless)
75
96
  end
76
97
 
77
98
  def _normalize_callback_option(options, from, to) # :nodoc:
78
- if from = options.delete(from)
79
- from = ActionFilter.new(from)
80
- options[to] = Array(options[to]).unshift(from)
99
+ if from_value = options.delete(from)
100
+ filters = options[:filters]
101
+ from_value = ActionFilter.new(filters, from, from_value)
102
+ options[to] = Array(options[to]).unshift(from_value)
81
103
  end
82
104
  end
83
105
 
84
- # Take callback names and an optional callback proc, normalize them,
85
- # then call the block with each callback. This allows us to abstract
86
- # the normalization across several methods that use it.
106
+ # Take callback names and an optional callback proc, normalize them, then call
107
+ # the block with each callback. This allows us to abstract the normalization
108
+ # across several methods that use it.
109
+ #
110
+ # #### Parameters
111
+ # * `callbacks` - An array of callbacks, with an optional options hash as the
112
+ # last parameter.
113
+ # * `block` - A proc that should be added to the callbacks.
114
+ #
87
115
  #
88
- # ==== Parameters
89
- # * <tt>callbacks</tt> - An array of callbacks, with an optional
90
- # options hash as the last parameter.
91
- # * <tt>block</tt> - A proc that should be added to the callbacks.
116
+ # #### Block Parameters
117
+ # * `name` - The callback to be added.
118
+ # * `options` - A hash of options to be used when adding the callback.
92
119
  #
93
- # ==== Block Parameters
94
- # * <tt>name</tt> - The callback to be added.
95
- # * <tt>options</tt> - A hash of options to be used when adding the callback.
96
120
  def _insert_callbacks(callbacks, block = nil)
97
121
  options = callbacks.extract_options!
98
- _normalize_callback_options(options)
99
122
  callbacks.push(block) if block
123
+ options[:filters] = callbacks
124
+ _normalize_callback_options(options)
125
+ options.delete(:filters)
100
126
  callbacks.each do |callback|
101
127
  yield callback, options
102
128
  end
@@ -109,20 +135,21 @@ module AbstractController
109
135
  #
110
136
  # Append a callback before actions. See _insert_callbacks for parameter details.
111
137
  #
112
- # If the callback renders or redirects, the action will not run. If there
113
- # are additional callbacks scheduled to run after that callback, they are
114
- # also cancelled.
138
+ # If the callback renders or redirects, the action will not run. If there are
139
+ # additional callbacks scheduled to run after that callback, they are also
140
+ # cancelled.
115
141
 
116
142
  ##
117
143
  # :method: prepend_before_action
118
144
  #
119
145
  # :call-seq: prepend_before_action(names, block)
120
146
  #
121
- # Prepend a callback before actions. See _insert_callbacks for parameter details.
147
+ # Prepend a callback before actions. See _insert_callbacks for parameter
148
+ # details.
122
149
  #
123
- # If the callback renders or redirects, the action will not run. If there
124
- # are additional callbacks scheduled to run after that callback, they are
125
- # also cancelled.
150
+ # If the callback renders or redirects, the action will not run. If there are
151
+ # additional callbacks scheduled to run after that callback, they are also
152
+ # cancelled.
126
153
 
127
154
  ##
128
155
  # :method: skip_before_action
@@ -138,9 +165,9 @@ module AbstractController
138
165
  #
139
166
  # Append a callback before actions. See _insert_callbacks for parameter details.
140
167
  #
141
- # If the callback renders or redirects, the action will not run. If there
142
- # are additional callbacks scheduled to run after that callback, they are
143
- # also cancelled.
168
+ # If the callback renders or redirects, the action will not run. If there are
169
+ # additional callbacks scheduled to run after that callback, they are also
170
+ # cancelled.
144
171
 
145
172
  ##
146
173
  # :method: after_action
@@ -182,7 +209,8 @@ module AbstractController
182
209
  #
183
210
  # :call-seq: prepend_around_action(names, block)
184
211
  #
185
- # Prepend a callback around actions. See _insert_callbacks for parameter details.
212
+ # Prepend a callback around actions. See _insert_callbacks for parameter
213
+ # details.
186
214
 
187
215
  ##
188
216
  # :method: skip_around_action
@@ -197,9 +225,8 @@ module AbstractController
197
225
  # :call-seq: append_around_action(names, block)
198
226
  #
199
227
  # Append a callback around actions. See _insert_callbacks for parameter details.
200
-
201
- # set up before_action, prepend_before_action, skip_before_action, etc.
202
- # for each of before, after, and around.
228
+ # set up before_action, prepend_before_action, skip_before_action, etc. for each
229
+ # of before, after, and around.
203
230
  [:before, :after, :around].each do |callback|
204
231
  define_method "#{callback}_action" do |*names, &blk|
205
232
  _insert_callbacks(names, blk) do |name, options|
@@ -213,8 +240,8 @@ module AbstractController
213
240
  end
214
241
  end
215
242
 
216
- # Skip a before, after or around callback. See _insert_callbacks
217
- # for details on the allowed parameters.
243
+ # Skip a before, after or around callback. See _insert_callbacks for details on
244
+ # the allowed parameters.
218
245
  define_method "skip_#{callback}_action" do |*names|
219
246
  _insert_callbacks(names) do |name, options|
220
247
  skip_callback(:process_action, callback, name, options)
@@ -227,8 +254,8 @@ module AbstractController
227
254
  end
228
255
 
229
256
  private
230
- # Override <tt>AbstractController::Base#process_action</tt> to run the
231
- # <tt>process_action</tt> callbacks around the normal behavior.
257
+ # Override `AbstractController::Base#process_action` to run the `process_action`
258
+ # callbacks around the normal behavior.
232
259
  def process_action(...)
233
260
  run_callbacks(:process_action) do
234
261
  super
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "action_dispatch/http/mime_type"
4
6
 
5
7
  module AbstractController
@@ -7,10 +9,9 @@ module AbstractController
7
9
  def self.generate_method_for_mime(mime)
8
10
  sym = mime.is_a?(Symbol) ? mime : mime.to_sym
9
11
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
10
- def #{sym}(*args, &block)
11
- custom(Mime[:#{sym}], *args, &block)
12
+ def #{sym}(...)
13
+ custom(Mime[:#{sym}], ...)
12
14
  end
13
- ruby2_keywords(:#{sym})
14
15
  RUBY
15
16
  end
16
17
 
@@ -23,7 +24,7 @@ module AbstractController
23
24
  end
24
25
 
25
26
  private
26
- def method_missing(symbol, *args, &block)
27
+ def method_missing(symbol, ...)
27
28
  unless mime_constant = Mime[symbol]
28
29
  raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
29
30
  "https://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
@@ -34,11 +35,10 @@ module AbstractController
34
35
 
35
36
  if Mime::SET.include?(mime_constant)
36
37
  AbstractController::Collector.generate_method_for_mime(mime_constant)
37
- public_send(symbol, *args, &block)
38
+ public_send(symbol, ...)
38
39
  else
39
40
  super
40
41
  end
41
42
  end
42
- ruby2_keywords(:method_missing)
43
43
  end
44
44
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module AbstractController
6
+ def self.deprecator # :nodoc:
7
+ @deprecator ||= ActiveSupport::Deprecation.new
8
+ end
9
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module AbstractController
4
6
  class Error < StandardError # :nodoc:
5
7
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/dependencies"
4
6
  require "active_support/core_ext/name_error"
5
7
 
@@ -10,8 +12,8 @@ module AbstractController
10
12
  included do
11
13
  class_attribute :_helper_methods, default: Array.new
12
14
 
13
- # This is here so that it is always higher in the inheritance chain than
14
- # the definition in lib/action_view/rendering.rb
15
+ # This is here so that it is always higher in the inheritance chain than the
16
+ # definition in lib/action_view/rendering.rb
15
17
  redefine_singleton_method(:_helpers) do
16
18
  if @_helpers ||= nil
17
19
  @_helpers
@@ -23,28 +25,46 @@ module AbstractController
23
25
  self._helpers = define_helpers_module(self)
24
26
  end
25
27
 
26
- class MissingHelperError < LoadError
27
- def initialize(error, path)
28
- @error = error
29
- @path = "helpers/#{path}.rb"
30
- set_backtrace error.backtrace
28
+ def _helpers
29
+ self.class._helpers
30
+ end
31
31
 
32
- if /^#{path}(\.rb)?$/.match?(error.path)
33
- super("Missing helper file helpers/%s.rb" % path)
34
- else
35
- raise error
32
+ module Resolution # :nodoc:
33
+ def modules_for_helpers(modules_or_helper_prefixes)
34
+ modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
35
+ case module_or_helper_prefix
36
+ when Module
37
+ module_or_helper_prefix
38
+ when String, Symbol
39
+ helper_prefix = module_or_helper_prefix.to_s
40
+ helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
41
+ "#{helper_prefix}Helper".constantize
42
+ else
43
+ raise ArgumentError, "helper must be a String, Symbol, or Module"
44
+ end
36
45
  end
37
46
  end
38
- end
39
47
 
40
- def _helpers
41
- self.class._helpers
48
+ def all_helpers_from_path(path)
49
+ helpers = Array(path).flat_map do |_path|
50
+ names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
51
+ names.sort!
52
+ end
53
+ helpers.uniq!
54
+ helpers
55
+ end
56
+
57
+ def helper_modules_from_paths(paths)
58
+ modules_for_helpers(all_helpers_from_path(paths))
59
+ end
42
60
  end
43
61
 
62
+ extend Resolution
63
+
44
64
  module ClassMethods
45
- # When a class is inherited, wrap its helper module in a new module.
46
- # This ensures that the parent class's module can be changed
47
- # independently of the child class's.
65
+ # When a class is inherited, wrap its helper module in a new module. This
66
+ # ensures that the parent class's module can be changed independently of the
67
+ # child class's.
48
68
  def inherited(klass)
49
69
  # Inherited from parent by default
50
70
  klass._helpers = nil
@@ -55,28 +75,56 @@ module AbstractController
55
75
 
56
76
  attr_writer :_helpers
57
77
 
78
+ include Resolution
79
+
80
+ ##
81
+ # :method: modules_for_helpers
82
+ # :call-seq: modules_for_helpers(modules_or_helper_prefixes)
83
+ #
84
+ # Given an array of values like the ones accepted by `helper`, this method
85
+ # returns an array with the corresponding modules, in the same order.
86
+ #
87
+ # ActionController::Base.modules_for_helpers(["application", "chart", "rubygems"])
88
+ # # => [ApplicationHelper, ChartHelper, RubygemsHelper]
89
+ #
90
+ #--
91
+ # Implemented by Resolution#modules_for_helpers.
92
+
93
+ # :method: # all_helpers_from_path
94
+ # :call-seq: all_helpers_from_path(path)
95
+ #
96
+ # Returns a list of helper names in a given path.
97
+ #
98
+ # ActionController::Base.all_helpers_from_path 'app/helpers'
99
+ # # => ["application", "chart", "rubygems"]
100
+ #
101
+ #--
102
+ # Implemented by Resolution#all_helpers_from_path.
103
+
58
104
  # Declare a controller method as a helper. For example, the following
59
- # makes the +current_user+ and +logged_in?+ controller methods available
105
+ # makes the `current_user` and `logged_in?` controller methods available
60
106
  # to the view:
61
- # class ApplicationController < ActionController::Base
62
- # helper_method :current_user, :logged_in?
63
107
  #
64
- # private
65
- # def current_user
66
- # @current_user ||= User.find_by(id: session[:user])
67
- # end
108
+ # class ApplicationController < ActionController::Base
109
+ # helper_method :current_user, :logged_in?
68
110
  #
69
- # def logged_in?
70
- # current_user != nil
71
- # end
72
- # end
111
+ # private
112
+ # def current_user
113
+ # @current_user ||= User.find_by(id: session[:user])
114
+ # end
115
+ #
116
+ # def logged_in?
117
+ # current_user != nil
118
+ # end
119
+ # end
73
120
  #
74
121
  # In a view:
75
- # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
76
122
  #
77
- # ==== Parameters
78
- # * <tt>method[, method]</tt> - A name or names of a method on the controller
79
- # to be made available on the view.
123
+ # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
124
+ #
125
+ # #### Parameters
126
+ # * `method[, method]` - A name or names of a method on the controller to be
127
+ # made available on the view.
80
128
  def helper_method(*methods)
81
129
  methods.flatten!
82
130
  self._helper_methods += methods
@@ -85,68 +133,67 @@ module AbstractController
85
133
  file, line = location.path, location.lineno
86
134
 
87
135
  methods.each do |method|
88
- # def current_user(*args, &block)
89
- # controller.send(:'current_user', *args, &block)
136
+ # def current_user(...)
137
+ # controller.send(:'current_user', ...)
90
138
  # end
91
139
  _helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
92
- def #{method}(*args, &block)
93
- controller.send(:'#{method}', *args, &block)
140
+ def #{method}(...)
141
+ controller.send(:'#{method}', ...)
94
142
  end
95
- ruby2_keywords(:'#{method}')
96
143
  ruby_eval
97
144
  end
98
145
  end
99
146
 
100
147
  # Includes the given modules in the template class.
101
148
  #
102
- # Modules can be specified in different ways. All of the following calls
103
- # include +FooHelper+:
149
+ # Modules can be specified in different ways. All of the following calls include
150
+ # `FooHelper`:
104
151
  #
105
- # # Module, recommended.
106
- # helper FooHelper
152
+ # # Module, recommended.
153
+ # helper FooHelper
107
154
  #
108
- # # String/symbol without the "helper" suffix, camel or snake case.
109
- # helper "Foo"
110
- # helper :Foo
111
- # helper "foo"
112
- # helper :foo
155
+ # # String/symbol without the "helper" suffix, camel or snake case.
156
+ # helper "Foo"
157
+ # helper :Foo
158
+ # helper "foo"
159
+ # helper :foo
113
160
  #
114
- # The last two assume that <tt>"foo".camelize</tt> returns "Foo".
161
+ # The last two assume that `"foo".camelize` returns "Foo".
115
162
  #
116
- # When strings or symbols are passed, the method finds the actual module
117
- # object using String#constantize. Therefore, if the module has not been
118
- # yet loaded, it has to be autoloadable, which is normally the case.
163
+ # When strings or symbols are passed, the method finds the actual module object
164
+ # using String#constantize. Therefore, if the module has not been yet loaded, it
165
+ # has to be autoloadable, which is normally the case.
119
166
  #
120
- # Namespaces are supported. The following calls include +Foo::BarHelper+:
167
+ # Namespaces are supported. The following calls include `Foo::BarHelper`:
121
168
  #
122
- # # Module, recommended.
123
- # helper Foo::BarHelper
169
+ # # Module, recommended.
170
+ # helper Foo::BarHelper
124
171
  #
125
- # # String/symbol without the "helper" suffix, camel or snake case.
126
- # helper "Foo::Bar"
127
- # helper :"Foo::Bar"
128
- # helper "foo/bar"
129
- # helper :"foo/bar"
172
+ # # String/symbol without the "helper" suffix, camel or snake case.
173
+ # helper "Foo::Bar"
174
+ # helper :"Foo::Bar"
175
+ # helper "foo/bar"
176
+ # helper :"foo/bar"
130
177
  #
131
- # The last two assume that <tt>"foo/bar".camelize</tt> returns "Foo::Bar".
178
+ # The last two assume that `"foo/bar".camelize` returns "Foo::Bar".
132
179
  #
133
- # The method accepts a block too. If present, the block is evaluated in
134
- # the context of the controller helper module. This simple call makes the
135
- # +wadus+ method available in templates of the enclosing controller:
180
+ # The method accepts a block too. If present, the block is evaluated in the
181
+ # context of the controller helper module. This simple call makes the `wadus`
182
+ # method available in templates of the enclosing controller:
136
183
  #
137
- # helper do
138
- # def wadus
139
- # "wadus"
184
+ # helper do
185
+ # def wadus
186
+ # "wadus"
187
+ # end
140
188
  # end
141
- # end
142
189
  #
143
190
  # Furthermore, all the above styles can be mixed together:
144
191
  #
145
- # helper FooHelper, "woo", "bar/baz" do
146
- # def wadus
147
- # "wadus"
192
+ # helper FooHelper, "woo", "bar/baz" do
193
+ # def wadus
194
+ # "wadus"
195
+ # end
148
196
  # end
149
- # end
150
197
  #
151
198
  def helper(*args, &block)
152
199
  modules_for_helpers(args).each do |mod|
@@ -157,8 +204,8 @@ module AbstractController
157
204
  _helpers_for_modification.module_eval(&block) if block_given?
158
205
  end
159
206
 
160
- # Clears up all existing helpers in this class, only keeping the helper
161
- # with the same name as this class.
207
+ # Clears up all existing helpers in this class, only keeping the helper with the
208
+ # same name as this class.
162
209
  def clear_helpers
163
210
  inherited_helper_methods = _helper_methods
164
211
  self._helpers = Module.new
@@ -168,23 +215,6 @@ module AbstractController
168
215
  default_helper_module! unless anonymous?
169
216
  end
170
217
 
171
- # Given an array of values like the ones accepted by +helper+, this method
172
- # returns an array with the corresponding modules, in the same order.
173
- def modules_for_helpers(modules_or_helper_prefixes)
174
- modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
175
- case module_or_helper_prefix
176
- when Module
177
- module_or_helper_prefix
178
- when String, Symbol
179
- helper_prefix = module_or_helper_prefix.to_s
180
- helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
181
- "#{helper_prefix}Helper".constantize
182
- else
183
- raise ArgumentError, "helper must be a String, Symbol, or Module"
184
- end
185
- end
186
- end
187
-
188
218
  def _helpers_for_modification
189
219
  unless @_helpers
190
220
  self._helpers = define_helpers_module(self, superclass._helpers)
@@ -194,8 +224,8 @@ module AbstractController
194
224
 
195
225
  private
196
226
  def define_helpers_module(klass, helpers = nil)
197
- # In some tests inherited is called explicitly. In that case, just
198
- # return the module from the first time it was defined
227
+ # In some tests inherited is called explicitly. In that case, just return the
228
+ # module from the first time it was defined
199
229
  return klass.const_get(:HelperMethods) if klass.const_defined?(:HelperMethods, false)
200
230
 
201
231
  mod = Module.new
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/benchmarkable"
4
6
 
5
7
  module AbstractController
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/module/introspection"
4
6
 
5
7
  module AbstractController
@@ -10,26 +12,11 @@ module AbstractController
10
12
  define_method(:inherited) do |klass|
11
13
  super(klass)
12
14
 
13
- namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
14
- actual_routes = namespace ? namespace.railtie_routes_url_helpers._routes : routes
15
-
16
- if namespace
15
+ if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
17
16
  klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
18
17
  else
19
18
  klass.include(routes.url_helpers(include_path_helpers))
20
19
  end
21
-
22
- # In the case that we have ex.
23
- # class A::Foo < ApplicationController
24
- # class Bar < A::Foo
25
- # We will need to redefine _routes because it will not be correct
26
- # via inheritance.
27
- unless klass._routes.equal?(actual_routes)
28
- klass.redefine_singleton_method(:_routes) { actual_routes }
29
- klass.include(Module.new do
30
- define_method(:_routes) { @_routes || actual_routes }
31
- end)
32
- end
33
20
  end
34
21
  end
35
22
  end