actionpack 6.1.7.5 → 7.1.3.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.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +355 -435
  3. data/MIT-LICENSE +2 -1
  4. data/README.rdoc +6 -7
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +33 -37
  7. data/lib/abstract_controller/caching/fragments.rb +4 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +50 -11
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/deprecator.rb +7 -0
  12. data/lib/abstract_controller/error.rb +1 -1
  13. data/lib/abstract_controller/helpers.rb +78 -30
  14. data/lib/abstract_controller/logger.rb +1 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
  16. data/lib/abstract_controller/rendering.rb +12 -14
  17. data/lib/abstract_controller/translation.rb +26 -7
  18. data/lib/abstract_controller/url_for.rb +6 -6
  19. data/lib/abstract_controller.rb +6 -0
  20. data/lib/action_controller/api.rb +12 -10
  21. data/lib/action_controller/base.rb +8 -21
  22. data/lib/action_controller/caching.rb +2 -0
  23. data/lib/action_controller/deprecator.rb +7 -0
  24. data/lib/action_controller/form_builder.rb +4 -2
  25. data/lib/action_controller/log_subscriber.rb +20 -7
  26. data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
  27. data/lib/action_controller/metal/conditional_get.rb +137 -102
  28. data/lib/action_controller/metal/content_security_policy.rb +37 -3
  29. data/lib/action_controller/metal/cookies.rb +1 -1
  30. data/lib/action_controller/metal/data_streaming.rb +25 -31
  31. data/lib/action_controller/metal/default_headers.rb +2 -0
  32. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
  34. data/lib/action_controller/metal/exceptions.rb +27 -30
  35. data/lib/action_controller/metal/flash.rb +6 -2
  36. data/lib/action_controller/metal/head.rb +9 -7
  37. data/lib/action_controller/metal/helpers.rb +5 -16
  38. data/lib/action_controller/metal/http_authentication.rb +78 -42
  39. data/lib/action_controller/metal/implicit_render.rb +5 -3
  40. data/lib/action_controller/metal/instrumentation.rb +62 -50
  41. data/lib/action_controller/metal/live.rb +67 -2
  42. data/lib/action_controller/metal/mime_responds.rb +5 -5
  43. data/lib/action_controller/metal/params_wrapper.rb +24 -13
  44. data/lib/action_controller/metal/permissions_policy.rb +20 -29
  45. data/lib/action_controller/metal/redirecting.rb +96 -23
  46. data/lib/action_controller/metal/renderers.rb +14 -15
  47. data/lib/action_controller/metal/rendering.rb +121 -16
  48. data/lib/action_controller/metal/request_forgery_protection.rb +208 -68
  49. data/lib/action_controller/metal/rescue.rb +7 -4
  50. data/lib/action_controller/metal/streaming.rb +74 -36
  51. data/lib/action_controller/metal/strong_parameters.rb +254 -151
  52. data/lib/action_controller/metal/testing.rb +9 -2
  53. data/lib/action_controller/metal/url_for.rb +10 -5
  54. data/lib/action_controller/metal.rb +89 -34
  55. data/lib/action_controller/railtie.rb +66 -9
  56. data/lib/action_controller/renderer.rb +99 -85
  57. data/lib/action_controller/test_case.rb +42 -11
  58. data/lib/action_controller.rb +10 -6
  59. data/lib/action_dispatch/constants.rb +32 -0
  60. data/lib/action_dispatch/deprecator.rb +7 -0
  61. data/lib/action_dispatch/http/cache.rb +21 -16
  62. data/lib/action_dispatch/http/content_security_policy.rb +122 -44
  63. data/lib/action_dispatch/http/filter_parameters.rb +14 -23
  64. data/lib/action_dispatch/http/headers.rb +3 -1
  65. data/lib/action_dispatch/http/mime_negotiation.rb +25 -15
  66. data/lib/action_dispatch/http/mime_type.rb +43 -22
  67. data/lib/action_dispatch/http/mime_types.rb +3 -1
  68. data/lib/action_dispatch/http/parameters.rb +6 -6
  69. data/lib/action_dispatch/http/permissions_policy.rb +57 -19
  70. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  71. data/lib/action_dispatch/http/request.rb +75 -51
  72. data/lib/action_dispatch/http/response.rb +81 -77
  73. data/lib/action_dispatch/http/upload.rb +15 -2
  74. data/lib/action_dispatch/http/url.rb +11 -19
  75. data/lib/action_dispatch/journey/formatter.rb +8 -2
  76. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  77. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  78. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  79. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  80. data/lib/action_dispatch/journey/path/pattern.rb +36 -27
  81. data/lib/action_dispatch/journey/route.rb +8 -14
  82. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  83. data/lib/action_dispatch/journey/router.rb +10 -9
  84. data/lib/action_dispatch/journey/routes.rb +5 -5
  85. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  86. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  87. data/lib/action_dispatch/log_subscriber.rb +23 -0
  88. data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -7
  89. data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
  90. data/lib/action_dispatch/middleware/callbacks.rb +2 -0
  91. data/lib/action_dispatch/middleware/cookies.rb +97 -107
  92. data/lib/action_dispatch/middleware/debug_exceptions.rb +31 -28
  93. data/lib/action_dispatch/middleware/debug_locks.rb +7 -4
  94. data/lib/action_dispatch/middleware/debug_view.rb +7 -2
  95. data/lib/action_dispatch/middleware/exception_wrapper.rb +190 -27
  96. data/lib/action_dispatch/middleware/executor.rb +3 -0
  97. data/lib/action_dispatch/middleware/flash.rb +24 -18
  98. data/lib/action_dispatch/middleware/host_authorization.rb +19 -20
  99. data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
  100. data/lib/action_dispatch/middleware/reloader.rb +7 -5
  101. data/lib/action_dispatch/middleware/remote_ip.rb +32 -19
  102. data/lib/action_dispatch/middleware/request_id.rb +5 -3
  103. data/lib/action_dispatch/middleware/server_timing.rb +76 -0
  104. data/lib/action_dispatch/middleware/session/abstract_store.rb +6 -1
  105. data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
  106. data/lib/action_dispatch/middleware/session/cookie_store.rb +19 -13
  107. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
  108. data/lib/action_dispatch/middleware/show_exceptions.rb +30 -25
  109. data/lib/action_dispatch/middleware/ssl.rb +18 -6
  110. data/lib/action_dispatch/middleware/stack.rb +34 -11
  111. data/lib/action_dispatch/middleware/static.rb +16 -16
  112. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  113. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +5 -5
  114. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  115. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  116. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  117. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
  118. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
  119. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +9 -9
  120. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  121. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  122. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +45 -18
  123. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -15
  124. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +4 -4
  125. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +6 -6
  126. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +7 -7
  127. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  128. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  129. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  130. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -55
  131. data/lib/action_dispatch/railtie.rb +20 -4
  132. data/lib/action_dispatch/request/session.rb +59 -19
  133. data/lib/action_dispatch/request/utils.rb +8 -3
  134. data/lib/action_dispatch/routing/inspector.rb +55 -7
  135. data/lib/action_dispatch/routing/mapper.rb +117 -107
  136. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  137. data/lib/action_dispatch/routing/redirection.rb +20 -8
  138. data/lib/action_dispatch/routing/route_set.rb +67 -27
  139. data/lib/action_dispatch/routing/routes_proxy.rb +11 -16
  140. data/lib/action_dispatch/routing/url_for.rb +29 -26
  141. data/lib/action_dispatch/routing.rb +12 -13
  142. data/lib/action_dispatch/system_test_case.rb +8 -8
  143. data/lib/action_dispatch/system_testing/browser.rb +20 -29
  144. data/lib/action_dispatch/system_testing/driver.rb +34 -18
  145. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +35 -20
  146. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
  147. data/lib/action_dispatch/testing/assertion_response.rb +1 -1
  148. data/lib/action_dispatch/testing/assertions/response.rb +14 -7
  149. data/lib/action_dispatch/testing/assertions/routing.rb +70 -30
  150. data/lib/action_dispatch/testing/assertions.rb +3 -4
  151. data/lib/action_dispatch/testing/integration.rb +33 -25
  152. data/lib/action_dispatch/testing/request_encoder.rb +4 -1
  153. data/lib/action_dispatch/testing/test_process.rb +5 -30
  154. data/lib/action_dispatch/testing/test_request.rb +1 -1
  155. data/lib/action_dispatch/testing/test_response.rb +34 -2
  156. data/lib/action_dispatch.rb +38 -4
  157. data/lib/action_pack/gem_version.rb +4 -4
  158. data/lib/action_pack/version.rb +1 -1
  159. data/lib/action_pack.rb +1 -1
  160. metadata +67 -30
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
@@ -18,3 +18,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.rdoc CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  Action Pack is a framework for handling and responding to web requests. It
4
4
  provides mechanisms for *routing* (mapping request URLs to actions), defining
5
- *controllers* that implement actions, and generating responses by rendering
6
- *views*, which are templates of various formats. In short, Action Pack
7
- provides the view and controller layers in the MVC paradigm.
5
+ *controllers* that implement actions, and generating responses. In short, Action Pack
6
+ provides the controller layer in the MVC paradigm.
8
7
 
9
8
  It consists of several modules:
10
9
 
@@ -17,11 +16,11 @@ It consists of several modules:
17
16
  subclassed to implement filters and actions to handle requests. The result
18
17
  of an action is typically content generated from views.
19
18
 
20
- 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
21
20
  Action Controller module. Necessary Action Dispatch functionality is activated
22
21
  by default and Action View rendering is implicitly triggered by Action
23
22
  Controller. However, these modules are designed to function on their own and
24
- can be used outside of Rails.
23
+ can be used outside of \Rails.
25
24
 
26
25
  You can read more about Action Pack in the {Action Controller Overview}[https://guides.rubyonrails.org/action_controller_overview.html] guide.
27
26
 
@@ -31,7 +30,7 @@ The latest version of Action Pack can be installed with RubyGems:
31
30
 
32
31
  $ gem install actionpack
33
32
 
34
- Source code can be downloaded as part of the Rails project on GitHub:
33
+ Source code can be downloaded as part of the \Rails project on GitHub:
35
34
 
36
35
  * https://github.com/rails/rails/tree/main/actionpack
37
36
 
@@ -49,7 +48,7 @@ API documentation is at:
49
48
 
50
49
  * https://api.rubyonrails.org
51
50
 
52
- Bug reports for the Ruby on Rails project can be filed here:
51
+ Bug reports for the Ruby on \Rails project can be filed here:
53
52
 
54
53
  * https://github.com/rails/rails/issues
55
54
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbstractController
4
- module AssetPaths #:nodoc:
4
+ module AssetPaths # :nodoc:
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
@@ -9,37 +9,25 @@ require "active_support/core_ext/module/attr_internal"
9
9
  module AbstractController
10
10
  # Raised when a non-existing controller action is triggered.
11
11
  class ActionNotFound < StandardError
12
- attr_reader :controller, :action
13
- def initialize(message = nil, controller = nil, action = nil)
12
+ attr_reader :controller, :action # :nodoc:
13
+
14
+ def initialize(message = nil, controller = nil, action = nil) # :nodoc:
14
15
  @controller = controller
15
16
  @action = action
16
17
  super(message)
17
18
  end
18
19
 
19
- class Correction
20
- def initialize(error)
21
- @error = error
22
- end
23
-
24
- def corrections
25
- if @error.action
26
- maybe_these = @error.controller.class.action_methods
20
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
21
+ include DidYouMean::Correctable # :nodoc:
27
22
 
28
- maybe_these.sort_by { |n|
29
- DidYouMean::Jaro.distance(@error.action.to_s, n)
30
- }.reverse.first(4)
31
- else
32
- []
33
- end
23
+ def corrections # :nodoc:
24
+ @corrections ||= DidYouMean::SpellChecker.new(dictionary: controller.class.action_methods).correct(action)
34
25
  end
35
26
  end
36
-
37
- # We may not have DYM, and DYM might not let us register error handlers
38
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
39
- DidYouMean.correct_error(self, Correction)
40
- end
41
27
  end
42
28
 
29
+ # = Abstract Controller \Base
30
+ #
43
31
  # AbstractController::Base is a low-level API. Nobody should be
44
32
  # using it directly, and subclasses (like ActionController::Base) are
45
33
  # expected to provide their own +render+ method, since rendering means
@@ -84,12 +72,17 @@ module AbstractController
84
72
  # instance methods on that abstract class. Public instance methods of
85
73
  # a controller would normally be considered action methods, so methods
86
74
  # declared on abstract classes are being removed.
87
- # (<tt>ActionController::Metal</tt> and ActionController::Base are defined as abstract)
75
+ # (ActionController::Metal and ActionController::Base are defined as abstract)
88
76
  def internal_methods
89
77
  controller = self
78
+ methods = []
90
79
 
91
- controller = controller.superclass until controller.abstract?
92
- controller.public_instance_methods(true)
80
+ until controller.abstract?
81
+ methods += controller.public_instance_methods(false)
82
+ controller = controller.superclass
83
+ end
84
+
85
+ controller.public_instance_methods(true) - methods
93
86
  end
94
87
 
95
88
  # A list of method names that should be considered actions. This
@@ -103,14 +96,11 @@ module AbstractController
103
96
  def action_methods
104
97
  @action_methods ||= begin
105
98
  # All public instance methods of this class, including ancestors
106
- methods = (public_instance_methods(true) -
107
- # Except for public instance methods of Base and its ancestors
108
- internal_methods +
109
- # Be sure to include shadowed public instance methods of this class
110
- public_instance_methods(false))
111
-
99
+ # except for public instance methods of Base and its ancestors.
100
+ methods = public_instance_methods(true) - internal_methods
101
+ # Be sure to include shadowed public instance methods of this class.
102
+ methods.concat(public_instance_methods(false))
112
103
  methods.map!(&:to_s)
113
-
114
104
  methods.to_set
115
105
  end
116
106
  end
@@ -141,11 +131,16 @@ module AbstractController
141
131
  super
142
132
  clear_action_methods!
143
133
  end
134
+
135
+ def eager_load! # :nodoc:
136
+ action_methods
137
+ nil
138
+ end
144
139
  end
145
140
 
146
141
  abstract!
147
142
 
148
- # Calls the action going through the entire action dispatch stack.
143
+ # Calls the action going through the entire Action Dispatch stack.
149
144
  #
150
145
  # The actual method that is called is determined by calling
151
146
  # #method_for_action. If no method can handle the action, then an
@@ -164,13 +159,14 @@ module AbstractController
164
159
 
165
160
  process_action(action_name, *args)
166
161
  end
162
+ ruby2_keywords(:process)
167
163
 
168
- # Delegates to the class' ::controller_path
164
+ # Delegates to the class's ::controller_path.
169
165
  def controller_path
170
166
  self.class.controller_path
171
167
  end
172
168
 
173
- # Delegates to the class' ::action_methods
169
+ # Delegates to the class's ::action_methods.
174
170
  def action_methods
175
171
  self.class.action_methods
176
172
  end
@@ -191,7 +187,7 @@ module AbstractController
191
187
 
192
188
  # Tests if a response body is set. Used to determine if the
193
189
  # +process_action+ callback needs to be terminated in
194
- # +AbstractController::Callbacks+.
190
+ # AbstractController::Callbacks.
195
191
  def performed?
196
192
  response_body
197
193
  end
@@ -224,8 +220,8 @@ module AbstractController
224
220
  #
225
221
  # Notice that the first argument is the method to be dispatched
226
222
  # which is *not* necessarily the same as the action name.
227
- def process_action(method_name, *args)
228
- send_action(method_name, *args)
223
+ def process_action(...)
224
+ send_action(...)
229
225
  end
230
226
 
231
227
  # Actually call the method associated with the action. Override
@@ -2,6 +2,8 @@
2
2
 
3
3
  module AbstractController
4
4
  module Caching
5
+ # = Abstract Controller Caching \Fragments
6
+ #
5
7
  # Fragment caching is used for caching various blocks within
6
8
  # views without caching the entire action as a whole. This is
7
9
  # useful when certain elements of an action change frequently or
@@ -142,8 +144,8 @@ module AbstractController
142
144
  end
143
145
  end
144
146
 
145
- def instrument_fragment_cache(name, key) # :nodoc:
146
- ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key)) { yield }
147
+ def instrument_fragment_cache(name, key, &block) # :nodoc:
148
+ ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key), &block)
147
149
  end
148
150
  end
149
151
  end
@@ -50,7 +50,7 @@ module AbstractController
50
50
  end
51
51
 
52
52
  def view_cache_dependencies
53
- self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact
53
+ self.class._view_cache_dependencies.filter_map { |dep| instance_exec(&dep) }
54
54
  end
55
55
 
56
56
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbstractController
4
- # = Abstract Controller Callbacks
4
+ # = Abstract Controller \Callbacks
5
5
  #
6
6
  # Abstract Controller provides hooks during the life cycle of a controller action.
7
7
  # Callbacks allow you to trigger logic during this cycle. Available callbacks are:
@@ -33,14 +33,42 @@ module AbstractController
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
- # Override <tt>AbstractController::Base#process_action</tt> to run the
39
- # <tt>process_action</tt> callbacks around the normal behavior.
40
- def process_action(*)
41
- run_callbacks(:process_action) do
42
- super
39
+ class ActionFilter # :nodoc:
40
+ def initialize(filters, conditional_key, actions)
41
+ @filters = filters.to_a
42
+ @conditional_key = conditional_key
43
+ @actions = Array(actions).map(&:to_s).to_set
43
44
  end
45
+
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
+
66
+ @actions.include?(controller.action_name)
67
+ end
68
+
69
+ alias after match?
70
+ alias before match?
71
+ alias around match?
44
72
  end
45
73
 
46
74
  module ClassMethods
@@ -69,10 +97,10 @@ module AbstractController
69
97
  end
70
98
 
71
99
  def _normalize_callback_option(options, from, to) # :nodoc:
72
- if from = options.delete(from)
73
- _from = Array(from).map(&:to_s).to_set
74
- from = proc { |c| _from.include? c.action_name }
75
- options[to] = Array(options[to]).unshift(from)
100
+ if from_value = options.delete(from)
101
+ filters = options[:filters]
102
+ from_value = ActionFilter.new(filters, from, from_value)
103
+ options[to] = Array(options[to]).unshift(from_value)
76
104
  end
77
105
  end
78
106
 
@@ -90,8 +118,10 @@ module AbstractController
90
118
  # * <tt>options</tt> - A hash of options to be used when adding the callback.
91
119
  def _insert_callbacks(callbacks, block = nil)
92
120
  options = callbacks.extract_options!
93
- _normalize_callback_options(options)
94
121
  callbacks.push(block) if block
122
+ options[:filters] = callbacks
123
+ _normalize_callback_options(options)
124
+ options.delete(:filters)
95
125
  callbacks.each do |callback|
96
126
  yield callback, options
97
127
  end
@@ -220,5 +250,14 @@ module AbstractController
220
250
  alias_method :"append_#{callback}_action", :"#{callback}_action"
221
251
  end
222
252
  end
253
+
254
+ private
255
+ # Override <tt>AbstractController::Base#process_action</tt> to run the
256
+ # <tt>process_action</tt> callbacks around the normal behavior.
257
+ def process_action(...)
258
+ run_callbacks(:process_action) do
259
+ super
260
+ end
261
+ end
223
262
  end
224
263
  end
@@ -10,7 +10,7 @@ module AbstractController
10
10
  def #{sym}(*args, &block)
11
11
  custom(Mime[:#{sym}], *args, &block)
12
12
  end
13
- ruby2_keywords(:#{sym}) if respond_to?(:ruby2_keywords, true)
13
+ ruby2_keywords(:#{sym})
14
14
  RUBY
15
15
  end
16
16
 
@@ -39,6 +39,6 @@ module AbstractController
39
39
  super
40
40
  end
41
41
  end
42
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
42
+ ruby2_keywords(:method_missing)
43
43
  end
44
44
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AbstractController
4
+ def self.deprecator # :nodoc:
5
+ @deprecator ||= ActiveSupport::Deprecation.new
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbstractController
4
- class Error < StandardError #:nodoc:
4
+ class Error < StandardError # :nodoc:
5
5
  end
6
6
  end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/dependencies"
4
+ require "active_support/core_ext/name_error"
4
5
 
5
6
  module AbstractController
6
7
  module Helpers
8
+ include ActiveSupport::Deprecation::DeprecatedConstantAccessor
7
9
  extend ActiveSupport::Concern
8
10
 
9
11
  included do
@@ -22,7 +24,7 @@ module AbstractController
22
24
  self._helpers = define_helpers_module(self)
23
25
  end
24
26
 
25
- class MissingHelperError < LoadError
27
+ class DeprecatedMissingHelperError < LoadError
26
28
  def initialize(error, path)
27
29
  @error = error
28
30
  @path = "helpers/#{path}.rb"
@@ -35,11 +37,46 @@ module AbstractController
35
37
  end
36
38
  end
37
39
  end
40
+ deprecate_constant "MissingHelperError", "AbstractController::Helpers::DeprecatedMissingHelperError",
41
+ message: "AbstractController::Helpers::MissingHelperError has been deprecated. If a Helper is not present, a NameError will be raised instead.",
42
+ deprecator: AbstractController.deprecator
38
43
 
39
44
  def _helpers
40
45
  self.class._helpers
41
46
  end
42
47
 
48
+ module Resolution # :nodoc:
49
+ def modules_for_helpers(modules_or_helper_prefixes)
50
+ modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
51
+ case module_or_helper_prefix
52
+ when Module
53
+ module_or_helper_prefix
54
+ when String, Symbol
55
+ helper_prefix = module_or_helper_prefix.to_s
56
+ helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
57
+ "#{helper_prefix}Helper".constantize
58
+ else
59
+ raise ArgumentError, "helper must be a String, Symbol, or Module"
60
+ end
61
+ end
62
+ end
63
+
64
+ def all_helpers_from_path(path)
65
+ helpers = Array(path).flat_map do |_path|
66
+ names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
67
+ names.sort!
68
+ end
69
+ helpers.uniq!
70
+ helpers
71
+ end
72
+
73
+ def helper_modules_from_paths(paths)
74
+ modules_for_helpers(all_helpers_from_path(paths))
75
+ end
76
+ end
77
+
78
+ extend Resolution
79
+
43
80
  module ClassMethods
44
81
  # When a class is inherited, wrap its helper module in a new module.
45
82
  # This ensures that the parent class's module can be changed
@@ -54,19 +91,44 @@ module AbstractController
54
91
 
55
92
  attr_writer :_helpers
56
93
 
94
+ include Resolution
95
+
96
+ ##
97
+ # :method: modules_for_helpers
98
+ # :call-seq: modules_for_helpers(modules_or_helper_prefixes)
99
+ #
100
+ # Given an array of values like the ones accepted by +helper+, this method
101
+ # returns an array with the corresponding modules, in the same order.
102
+ #
103
+ #--
104
+ # Implemented by Resolution#modules_for_helpers.
105
+
106
+ ##
107
+ # :method: all_helpers_from_path
108
+ # :call-seq: all_helpers_from_path(path)
109
+ #
110
+ # Returns a list of helper names in a given path.
111
+ #
112
+ # ActionController::Base.all_helpers_from_path 'app/helpers'
113
+ # # => ["application", "chart", "rubygems"]
114
+ #
115
+ #--
116
+ # Implemented by Resolution#all_helpers_from_path.
117
+
57
118
  # Declare a controller method as a helper. For example, the following
58
119
  # makes the +current_user+ and +logged_in?+ controller methods available
59
120
  # to the view:
60
121
  # class ApplicationController < ActionController::Base
61
122
  # helper_method :current_user, :logged_in?
62
123
  #
63
- # def current_user
64
- # @current_user ||= User.find_by(id: session[:user])
65
- # end
124
+ # private
125
+ # def current_user
126
+ # @current_user ||= User.find_by(id: session[:user])
127
+ # end
66
128
  #
67
- # def logged_in?
68
- # current_user != nil
69
- # end
129
+ # def logged_in?
130
+ # current_user != nil
131
+ # end
70
132
  # end
71
133
  #
72
134
  # In a view:
@@ -83,11 +145,14 @@ module AbstractController
83
145
  file, line = location.path, location.lineno
84
146
 
85
147
  methods.each do |method|
86
- _helpers_for_modification.class_eval <<-ruby_eval, file, line
87
- def #{method}(*args, &block) # def current_user(*args, &block)
88
- controller.send(:'#{method}', *args, &block) # controller.send(:'current_user', *args, &block)
89
- end # end
90
- ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
148
+ # def current_user(*args, &block)
149
+ # controller.send(:'current_user', *args, &block)
150
+ # end
151
+ _helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
152
+ def #{method}(*args, &block)
153
+ controller.send(:'#{method}', *args, &block)
154
+ end
155
+ ruby2_keywords(:'#{method}')
91
156
  ruby_eval
92
157
  end
93
158
  end
@@ -109,7 +174,7 @@ module AbstractController
109
174
  # The last two assume that <tt>"foo".camelize</tt> returns "Foo".
110
175
  #
111
176
  # When strings or symbols are passed, the method finds the actual module
112
- # object using +String#constantize+. Therefore, if the module has not been
177
+ # object using String#constantize. Therefore, if the module has not been
113
178
  # yet loaded, it has to be autoloadable, which is normally the case.
114
179
  #
115
180
  # Namespaces are supported. The following calls include +Foo::BarHelper+:
@@ -163,23 +228,6 @@ module AbstractController
163
228
  default_helper_module! unless anonymous?
164
229
  end
165
230
 
166
- # Given an array of values like the ones accepted by +helper+, this method
167
- # returns an array with the corresponding modules, in the same order.
168
- def modules_for_helpers(modules_or_helper_prefixes)
169
- modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
170
- case module_or_helper_prefix
171
- when Module
172
- module_or_helper_prefix
173
- when String, Symbol
174
- helper_prefix = module_or_helper_prefix.to_s
175
- helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
176
- "#{helper_prefix}Helper".constantize
177
- else
178
- raise ArgumentError, "helper must be a String, Symbol, or Module"
179
- end
180
- end
181
- end
182
-
183
231
  def _helpers_for_modification
184
232
  unless @_helpers
185
233
  self._helpers = define_helpers_module(self, superclass._helpers)
@@ -3,7 +3,7 @@
3
3
  require "active_support/benchmarkable"
4
4
 
5
5
  module AbstractController
6
- module Logger #:nodoc:
6
+ module Logger # :nodoc:
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/module/introspection"
4
+
3
5
  module AbstractController
4
6
  module Railties
5
7
  module RoutesHelpers
@@ -8,26 +10,11 @@ module AbstractController
8
10
  define_method(:inherited) do |klass|
9
11
  super(klass)
10
12
 
11
- namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
12
- actual_routes = namespace ? namespace.railtie_routes_url_helpers._routes : routes
13
-
14
- if namespace
13
+ if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
15
14
  klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
16
15
  else
17
16
  klass.include(routes.url_helpers(include_path_helpers))
18
17
  end
19
-
20
- # In the case that we have ex.
21
- # class A::Foo < ApplicationController
22
- # class Bar < A::Foo
23
- # We will need to redefine _routes because it will not be correct
24
- # via inheritance.
25
- unless klass._routes.equal?(actual_routes)
26
- klass.redefine_singleton_method(:_routes) { actual_routes }
27
- klass.include(Module.new do
28
- define_method(:_routes) { @_routes || actual_routes }
29
- end)
30
- end
31
18
  end
32
19
  end
33
20
  end
@@ -7,7 +7,7 @@ require "set"
7
7
 
8
8
  module AbstractController
9
9
  class DoubleRenderError < Error
10
- DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
10
+ DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...); return\"."
11
11
 
12
12
  def initialize(message = nil)
13
13
  super(message || DEFAULT_MESSAGE)
@@ -18,8 +18,10 @@ module AbstractController
18
18
  extend ActiveSupport::Concern
19
19
  include ActionView::ViewPaths
20
20
 
21
- # Normalizes arguments, options and then delegates render_to_body and
21
+ # Normalizes arguments and options, and then delegates to render_to_body and
22
22
  # sticks the result in <tt>self.response_body</tt>.
23
+ #
24
+ # Supported options depend on the underlying +render_to_body+ implementation.
23
25
  def render(*args, &block)
24
26
  options = _normalize_render(*args, &block)
25
27
  rendered_body = render_to_body(options)
@@ -32,16 +34,12 @@ module AbstractController
32
34
  self.response_body = rendered_body
33
35
  end
34
36
 
35
- # Raw rendering of a template to a string.
36
- #
37
- # It is similar to render, except that it does not
38
- # set the +response_body+ and it should be guaranteed
39
- # to always return a string.
37
+ # Similar to #render, but only returns the rendered template as a string,
38
+ # instead of setting +self.response_body+.
40
39
  #
41
- # If a component extends the semantics of +response_body+
42
- # (as ActionController extends it to be anything that
43
- # responds to the method each), this method needs to be
44
- # overridden in order to still return a string.
40
+ # If a component extends the semantics of +response_body+ (as ActionController
41
+ # extends it to be anything that responds to the method each), this method
42
+ # needs to be overridden in order to still return a string.
45
43
  def render_to_string(*args, &block)
46
44
  options = _normalize_render(*args, &block)
47
45
  render_to_body(options)
@@ -51,7 +49,7 @@ module AbstractController
51
49
  def render_to_body(options = {})
52
50
  end
53
51
 
54
- # Returns Content-Type of rendered content.
52
+ # Returns +Content-Type+ of rendered content.
55
53
  def rendered_format
56
54
  Mime[:text]
57
55
  end
@@ -70,8 +68,8 @@ module AbstractController
70
68
 
71
69
  private
72
70
  # Normalize args by converting <tt>render "foo"</tt> to
73
- # <tt>render :action => "foo"</tt> and <tt>render "foo/bar"</tt> to
74
- # <tt>render :file => "foo/bar"</tt>.
71
+ # <tt>render action: "foo"</tt> and <tt>render "foo/bar"</tt> to
72
+ # <tt>render file: "foo/bar"</tt>.
75
73
  def _normalize_args(action = nil, options = {}) # :doc:
76
74
  if action.respond_to?(:permitted?)
77
75
  if action.permitted?