actionpack 7.0.5 → 7.1.3.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +368 -315
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/abstract_controller/base.rb +20 -11
  6. data/lib/abstract_controller/caching/fragments.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +31 -6
  8. data/lib/abstract_controller/deprecator.rb +7 -0
  9. data/lib/abstract_controller/helpers.rb +68 -22
  10. data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
  11. data/lib/abstract_controller/rendering.rb +3 -3
  12. data/lib/abstract_controller/translation.rb +9 -6
  13. data/lib/abstract_controller/url_for.rb +2 -0
  14. data/lib/abstract_controller.rb +6 -0
  15. data/lib/action_controller/api.rb +5 -3
  16. data/lib/action_controller/base.rb +3 -17
  17. data/lib/action_controller/caching.rb +2 -0
  18. data/lib/action_controller/deprecator.rb +7 -0
  19. data/lib/action_controller/form_builder.rb +2 -0
  20. data/lib/action_controller/log_subscriber.rb +16 -4
  21. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +2 -0
  23. data/lib/action_controller/metal/default_headers.rb +2 -0
  24. data/lib/action_controller/metal/etag_with_flash.rb +2 -0
  25. data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
  26. data/lib/action_controller/metal/exceptions.rb +8 -0
  27. data/lib/action_controller/metal/head.rb +8 -6
  28. data/lib/action_controller/metal/helpers.rb +3 -14
  29. data/lib/action_controller/metal/http_authentication.rb +17 -8
  30. data/lib/action_controller/metal/implicit_render.rb +5 -3
  31. data/lib/action_controller/metal/instrumentation.rb +8 -1
  32. data/lib/action_controller/metal/live.rb +24 -0
  33. data/lib/action_controller/metal/mime_responds.rb +2 -2
  34. data/lib/action_controller/metal/params_wrapper.rb +4 -2
  35. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  36. data/lib/action_controller/metal/redirecting.rb +24 -7
  37. data/lib/action_controller/metal/renderers.rb +4 -4
  38. data/lib/action_controller/metal/rendering.rb +0 -7
  39. data/lib/action_controller/metal/request_forgery_protection.rb +139 -50
  40. data/lib/action_controller/metal/rescue.rb +6 -3
  41. data/lib/action_controller/metal/streaming.rb +70 -30
  42. data/lib/action_controller/metal/strong_parameters.rb +158 -101
  43. data/lib/action_controller/metal/url_for.rb +7 -0
  44. data/lib/action_controller/metal.rb +79 -21
  45. data/lib/action_controller/railtie.rb +22 -9
  46. data/lib/action_controller/renderer.rb +98 -65
  47. data/lib/action_controller/test_case.rb +15 -5
  48. data/lib/action_controller.rb +8 -1
  49. data/lib/action_dispatch/constants.rb +32 -0
  50. data/lib/action_dispatch/deprecator.rb +7 -0
  51. data/lib/action_dispatch/http/cache.rb +1 -3
  52. data/lib/action_dispatch/http/content_security_policy.rb +9 -8
  53. data/lib/action_dispatch/http/filter_parameters.rb +11 -5
  54. data/lib/action_dispatch/http/headers.rb +2 -0
  55. data/lib/action_dispatch/http/mime_negotiation.rb +22 -22
  56. data/lib/action_dispatch/http/mime_type.rb +35 -12
  57. data/lib/action_dispatch/http/mime_types.rb +3 -1
  58. data/lib/action_dispatch/http/parameters.rb +1 -1
  59. data/lib/action_dispatch/http/permissions_policy.rb +38 -23
  60. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  61. data/lib/action_dispatch/http/request.rb +48 -14
  62. data/lib/action_dispatch/http/response.rb +80 -59
  63. data/lib/action_dispatch/http/upload.rb +2 -0
  64. data/lib/action_dispatch/journey/formatter.rb +8 -2
  65. data/lib/action_dispatch/journey/path/pattern.rb +14 -14
  66. data/lib/action_dispatch/journey/route.rb +3 -2
  67. data/lib/action_dispatch/journey/router.rb +9 -8
  68. data/lib/action_dispatch/journey/routes.rb +2 -2
  69. data/lib/action_dispatch/log_subscriber.rb +23 -0
  70. data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
  71. data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
  72. data/lib/action_dispatch/middleware/callbacks.rb +2 -0
  73. data/lib/action_dispatch/middleware/cookies.rb +81 -98
  74. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
  75. data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
  76. data/lib/action_dispatch/middleware/debug_view.rb +7 -2
  77. data/lib/action_dispatch/middleware/exception_wrapper.rb +186 -27
  78. data/lib/action_dispatch/middleware/executor.rb +1 -1
  79. data/lib/action_dispatch/middleware/flash.rb +7 -0
  80. data/lib/action_dispatch/middleware/host_authorization.rb +18 -8
  81. data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
  82. data/lib/action_dispatch/middleware/reloader.rb +7 -5
  83. data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
  84. data/lib/action_dispatch/middleware/request_id.rb +2 -0
  85. data/lib/action_dispatch/middleware/server_timing.rb +4 -4
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
  89. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
  90. data/lib/action_dispatch/middleware/show_exceptions.rb +25 -18
  91. data/lib/action_dispatch/middleware/ssl.rb +18 -6
  92. data/lib/action_dispatch/middleware/stack.rb +7 -2
  93. data/lib/action_dispatch/middleware/static.rb +12 -8
  94. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  95. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  96. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  97. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -3
  98. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -3
  99. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  100. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  101. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  102. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  103. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  104. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  105. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  106. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  108. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  109. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
  110. data/lib/action_dispatch/railtie.rb +14 -4
  111. data/lib/action_dispatch/request/session.rb +16 -6
  112. data/lib/action_dispatch/request/utils.rb +8 -3
  113. data/lib/action_dispatch/routing/inspector.rb +54 -6
  114. data/lib/action_dispatch/routing/mapper.rb +35 -24
  115. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  116. data/lib/action_dispatch/routing/redirection.rb +15 -6
  117. data/lib/action_dispatch/routing/route_set.rb +52 -22
  118. data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
  119. data/lib/action_dispatch/routing/url_for.rb +5 -1
  120. data/lib/action_dispatch/routing.rb +7 -7
  121. data/lib/action_dispatch/system_test_case.rb +3 -3
  122. data/lib/action_dispatch/system_testing/browser.rb +20 -19
  123. data/lib/action_dispatch/system_testing/driver.rb +13 -21
  124. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
  125. data/lib/action_dispatch/testing/assertion_response.rb +1 -1
  126. data/lib/action_dispatch/testing/assertions/response.rb +13 -6
  127. data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
  128. data/lib/action_dispatch/testing/assertions.rb +3 -1
  129. data/lib/action_dispatch/testing/integration.rb +27 -17
  130. data/lib/action_dispatch/testing/request_encoder.rb +4 -1
  131. data/lib/action_dispatch/testing/test_process.rb +4 -3
  132. data/lib/action_dispatch/testing/test_request.rb +1 -1
  133. data/lib/action_dispatch/testing/test_response.rb +23 -9
  134. data/lib/action_dispatch.rb +37 -4
  135. data/lib/action_pack/gem_version.rb +4 -4
  136. data/lib/action_pack/version.rb +1 -1
  137. data/lib/action_pack.rb +1 -1
  138. metadata +67 -31
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
 
@@ -30,7 +30,7 @@ The latest version of Action Pack can be installed with RubyGems:
30
30
 
31
31
  $ gem install actionpack
32
32
 
33
- 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:
34
34
 
35
35
  * https://github.com/rails/rails/tree/main/actionpack
36
36
 
@@ -48,7 +48,7 @@ API documentation is at:
48
48
 
49
49
  * https://api.rubyonrails.org
50
50
 
51
- 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:
52
52
 
53
53
  * https://github.com/rails/rails/issues
54
54
 
@@ -26,6 +26,8 @@ module AbstractController
26
26
  end
27
27
  end
28
28
 
29
+ # = Abstract Controller \Base
30
+ #
29
31
  # AbstractController::Base is a low-level API. Nobody should be
30
32
  # using it directly, and subclasses (like ActionController::Base) are
31
33
  # expected to provide their own +render+ method, since rendering means
@@ -70,12 +72,17 @@ module AbstractController
70
72
  # instance methods on that abstract class. Public instance methods of
71
73
  # a controller would normally be considered action methods, so methods
72
74
  # declared on abstract classes are being removed.
73
- # (<tt>ActionController::Metal</tt> and ActionController::Base are defined as abstract)
75
+ # (ActionController::Metal and ActionController::Base are defined as abstract)
74
76
  def internal_methods
75
77
  controller = self
78
+ methods = []
76
79
 
77
- controller = controller.superclass until controller.abstract?
78
- 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
79
86
  end
80
87
 
81
88
  # A list of method names that should be considered actions. This
@@ -89,14 +96,11 @@ module AbstractController
89
96
  def action_methods
90
97
  @action_methods ||= begin
91
98
  # 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
+ # 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))
98
103
  methods.map!(&:to_s)
99
-
100
104
  methods.to_set
101
105
  end
102
106
  end
@@ -127,11 +131,16 @@ module AbstractController
127
131
  super
128
132
  clear_action_methods!
129
133
  end
134
+
135
+ def eager_load! # :nodoc:
136
+ action_methods
137
+ nil
138
+ end
130
139
  end
131
140
 
132
141
  abstract!
133
142
 
134
- # Calls the action going through the entire action dispatch stack.
143
+ # Calls the action going through the entire Action Dispatch stack.
135
144
  #
136
145
  # The actual method that is called is determined by calling
137
146
  # #method_for_action. If no method can handle the action, then an
@@ -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
@@ -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,36 @@ 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
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
 
@@ -75,9 +97,10 @@ module AbstractController
75
97
  end
76
98
 
77
99
  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)
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)
81
104
  end
82
105
  end
83
106
 
@@ -95,8 +118,10 @@ module AbstractController
95
118
  # * <tt>options</tt> - A hash of options to be used when adding the callback.
96
119
  def _insert_callbacks(callbacks, block = nil)
97
120
  options = callbacks.extract_options!
98
- _normalize_callback_options(options)
99
121
  callbacks.push(block) if block
122
+ options[:filters] = callbacks
123
+ _normalize_callback_options(options)
124
+ options.delete(:filters)
100
125
  callbacks.each do |callback|
101
126
  yield callback, options
102
127
  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
@@ -5,6 +5,7 @@ require "active_support/core_ext/name_error"
5
5
 
6
6
  module AbstractController
7
7
  module Helpers
8
+ include ActiveSupport::Deprecation::DeprecatedConstantAccessor
8
9
  extend ActiveSupport::Concern
9
10
 
10
11
  included do
@@ -23,7 +24,7 @@ module AbstractController
23
24
  self._helpers = define_helpers_module(self)
24
25
  end
25
26
 
26
- class MissingHelperError < LoadError
27
+ class DeprecatedMissingHelperError < LoadError
27
28
  def initialize(error, path)
28
29
  @error = error
29
30
  @path = "helpers/#{path}.rb"
@@ -36,11 +37,46 @@ module AbstractController
36
37
  end
37
38
  end
38
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
39
43
 
40
44
  def _helpers
41
45
  self.class._helpers
42
46
  end
43
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
+
44
80
  module ClassMethods
45
81
  # When a class is inherited, wrap its helper module in a new module.
46
82
  # This ensures that the parent class's module can be changed
@@ -55,6 +91,30 @@ module AbstractController
55
91
 
56
92
  attr_writer :_helpers
57
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
+
58
118
  # Declare a controller method as a helper. For example, the following
59
119
  # makes the +current_user+ and +logged_in?+ controller methods available
60
120
  # to the view:
@@ -85,10 +145,13 @@ module AbstractController
85
145
  file, line = location.path, location.lineno
86
146
 
87
147
  methods.each do |method|
88
- _helpers_for_modification.class_eval <<~ruby_eval, file, line
89
- def #{method}(*args, &block) # def current_user(*args, &block)
90
- controller.send(:'#{method}', *args, &block) # controller.send(:'current_user', *args, &block)
91
- end # end
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
92
155
  ruby2_keywords(:'#{method}')
93
156
  ruby_eval
94
157
  end
@@ -165,23 +228,6 @@ module AbstractController
165
228
  default_helper_module! unless anonymous?
166
229
  end
167
230
 
168
- # Given an array of values like the ones accepted by +helper+, this method
169
- # returns an array with the corresponding modules, in the same order.
170
- def modules_for_helpers(modules_or_helper_prefixes)
171
- modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
172
- case module_or_helper_prefix
173
- when Module
174
- module_or_helper_prefix
175
- when String, Symbol
176
- helper_prefix = module_or_helper_prefix.to_s
177
- helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
178
- "#{helper_prefix}Helper".constantize
179
- else
180
- raise ArgumentError, "helper must be a String, Symbol, or Module"
181
- end
182
- end
183
- end
184
-
185
231
  def _helpers_for_modification
186
232
  unless @_helpers
187
233
  self._helpers = define_helpers_module(self, superclass._helpers)
@@ -10,26 +10,11 @@ module AbstractController
10
10
  define_method(:inherited) do |klass|
11
11
  super(klass)
12
12
 
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
13
+ if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
17
14
  klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
18
15
  else
19
16
  klass.include(routes.url_helpers(include_path_helpers))
20
17
  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
18
  end
34
19
  end
35
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)
@@ -68,8 +68,8 @@ module AbstractController
68
68
 
69
69
  private
70
70
  # Normalize args by converting <tt>render "foo"</tt> to
71
- # <tt>render :action => "foo"</tt> and <tt>render "foo/bar"</tt> to
72
- # <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>.
73
73
  def _normalize_args(action = nil, options = {}) # :doc:
74
74
  if action.respond_to?(:permitted?)
75
75
  if action.permitted?
@@ -4,9 +4,7 @@ require "active_support/html_safe_translation"
4
4
 
5
5
  module AbstractController
6
6
  module Translation
7
- mattr_accessor :raise_on_missing_translations, default: false
8
-
9
- # Delegates to <tt>I18n.translate</tt>. Also aliased as <tt>t</tt>.
7
+ # Delegates to <tt>I18n.translate</tt>.
10
8
  #
11
9
  # When the given key starts with a period, it will be scoped by the current
12
10
  # controller and action. So if you call <tt>translate(".foo")</tt> from
@@ -23,13 +21,18 @@ module AbstractController
23
21
  key = "#{path}.#{action_name}#{key}"
24
22
  end
25
23
 
26
- i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
24
+ if options[:default]
25
+ options[:default] = [options[:default]] unless options[:default].is_a?(Array)
26
+ options[:default] = options[:default].map do |value|
27
+ value.is_a?(String) ? ERB::Util.html_escape(value) : value
28
+ end
29
+ end
27
30
 
28
- ActiveSupport::HtmlSafeTranslation.translate(key, **options, raise: i18n_raise)
31
+ ActiveSupport::HtmlSafeTranslation.translate(key, **options)
29
32
  end
30
33
  alias :t :translate
31
34
 
32
- # Delegates to <tt>I18n.localize</tt>. Also aliased as <tt>l</tt>.
35
+ # Delegates to <tt>I18n.localize</tt>.
33
36
  def localize(object, **options)
34
37
  I18n.localize(object, **options)
35
38
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbstractController
4
+ # = URL For
5
+ #
4
6
  # Includes +url_for+ into the host class (e.g. an abstract controller or mailer). The class
5
7
  # has to provide a +RouteSet+ by implementing the <tt>_routes</tt> methods. Otherwise, an
6
8
  # exception will be raised.
@@ -4,6 +4,7 @@ require "action_pack"
4
4
  require "active_support"
5
5
  require "active_support/rails"
6
6
  require "active_support/i18n"
7
+ require "abstract_controller/deprecator"
7
8
 
8
9
  module AbstractController
9
10
  extend ActiveSupport::Autoload
@@ -24,5 +25,10 @@ module AbstractController
24
25
  def self.eager_load!
25
26
  super
26
27
  AbstractController::Caching.eager_load!
28
+ AbstractController::Base.descendants.each do |controller|
29
+ unless controller.abstract?
30
+ controller.eager_load!
31
+ end
32
+ end
27
33
  end
28
34
  end
@@ -5,6 +5,8 @@ require "action_controller"
5
5
  require "action_controller/log_subscriber"
6
6
 
7
7
  module ActionController
8
+ # = Action Controller \API
9
+ #
8
10
  # API Controller is a lightweight version of ActionController::Base,
9
11
  # created for applications that don't require all functionalities that a complete
10
12
  # \Rails controller provides, allowing you to create controllers with just the
@@ -19,7 +21,7 @@ module ActionController
19
21
  # your application, they're just not part of the default API controller stack.
20
22
  #
21
23
  # Normally, +ApplicationController+ is the only controller that inherits from
22
- # <tt>ActionController::API</tt>. All other controllers in turn inherit from
24
+ # +ActionController::API+. All other controllers in turn inherit from
23
25
  # +ApplicationController+.
24
26
  #
25
27
  # A sample controller could look like this:
@@ -62,7 +64,7 @@ module ActionController
62
64
  #
63
65
  # In some scenarios you may want to add back some functionality provided by
64
66
  # ActionController::Base that is not present by default in
65
- # <tt>ActionController::API</tt>, for instance <tt>MimeResponds</tt>. This
67
+ # +ActionController::API+, for instance <tt>MimeResponds</tt>. This
66
68
  # module gives you the <tt>respond_to</tt> method. Adding it is quite simple,
67
69
  # you just need to include the module in a specific controller or in
68
70
  # +ApplicationController+ in case you want it available in your entire
@@ -85,7 +87,7 @@ module ActionController
85
87
  #
86
88
  # Make sure to check the modules included in ActionController::Base
87
89
  # if you want to use any other functionality that is not provided
88
- # by <tt>ActionController::API</tt> out of the box.
90
+ # by +ActionController::API+ out of the box.
89
91
  class API < Metal
90
92
  abstract!
91
93
 
@@ -5,11 +5,13 @@ require "action_controller/log_subscriber"
5
5
  require "action_controller/metal/params_wrapper"
6
6
 
7
7
  module ActionController
8
+ # = Action Controller \Base
9
+ #
8
10
  # Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
9
11
  # on request and then either it renders a template or redirects to another action. An action is defined as a public method
10
12
  # on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
11
13
  #
12
- # By default, only the ApplicationController in a \Rails application inherits from <tt>ActionController::Base</tt>. All other
14
+ # By default, only the ApplicationController in a \Rails application inherits from +ActionController::Base+. All other
13
15
  # controllers inherit from ApplicationController. This gives you one class to configure things such as
14
16
  # request forgery protection and filtering of sensitive request parameters.
15
17
  #
@@ -167,22 +169,6 @@ module ActionController
167
169
  class Base < Metal
168
170
  abstract!
169
171
 
170
- # We document the request and response methods here because albeit they are
171
- # implemented in ActionController::Metal, the type of the returned objects
172
- # is unknown at that level.
173
-
174
- ##
175
- # :method: request
176
- #
177
- # Returns an ActionDispatch::Request instance that represents the
178
- # current request.
179
-
180
- ##
181
- # :method: response
182
- #
183
- # Returns an ActionDispatch::Response that represents the current
184
- # response.
185
-
186
172
  # Shortcut helper that returns all the modules included in
187
173
  # ActionController::Base except the ones passed as arguments:
188
174
  #
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
+ # = Action Controller \Caching
5
+ #
4
6
  # \Caching is a cheap way of speeding up slow applications by keeping the result of
5
7
  # calculations, renderings, and database calls around for subsequent requests.
6
8
  #
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionController
4
+ def self.deprecator # :nodoc:
5
+ AbstractController.deprecator
6
+ end
7
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
+ # = Action Controller Form Builder
5
+ #
4
6
  # Override the default form builder for all views rendered by this
5
7
  # controller and any of its descendants. Accepts a subclass of
6
8
  # ActionView::Helpers::FormBuilder.
@@ -8,7 +8,10 @@ module ActionController
8
8
  return unless logger.info?
9
9
 
10
10
  payload = event.payload
11
- params = payload[:params].except(*INTERNAL_PARAMS)
11
+ params = {}
12
+ payload[:params].each_pair do |k, v|
13
+ params[k] = v unless INTERNAL_PARAMS.include?(k)
14
+ end
12
15
  format = payload[:format]
13
16
  format = format.to_s.upcase if format.is_a?(Symbol)
14
17
  format = "*/*" if format.nil?
@@ -16,6 +19,7 @@ module ActionController
16
19
  info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}"
17
20
  info " Parameters: #{params.inspect}" unless params.empty?
18
21
  end
22
+ subscribe_log_level :start_processing, :info
19
23
 
20
24
  def process_action(event)
21
25
  info do
@@ -29,29 +33,34 @@ module ActionController
29
33
 
30
34
  additions << "Allocations: #{event.allocations}"
31
35
 
32
- message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
33
- message << " (#{additions.join(" | ")})"
36
+ message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms" \
37
+ " (#{additions.join(" | ")})"
34
38
  message << "\n\n" if defined?(Rails.env) && Rails.env.development?
35
39
 
36
40
  message
37
41
  end
38
42
  end
43
+ subscribe_log_level :process_action, :info
39
44
 
40
45
  def halted_callback(event)
41
46
  info { "Filter chain halted as #{event.payload[:filter].inspect} rendered or redirected" }
42
47
  end
48
+ subscribe_log_level :halted_callback, :info
43
49
 
44
50
  def send_file(event)
45
51
  info { "Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)" }
46
52
  end
53
+ subscribe_log_level :send_file, :info
47
54
 
48
55
  def redirect_to(event)
49
56
  info { "Redirected to #{event.payload[:location]}" }
50
57
  end
58
+ subscribe_log_level :redirect_to, :info
51
59
 
52
60
  def send_data(event)
53
61
  info { "Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)" }
54
62
  end
63
+ subscribe_log_level :send_data, :info
55
64
 
56
65
  def unpermitted_parameters(event)
57
66
  debug do
@@ -61,15 +70,18 @@ module ActionController
61
70
  color("Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{display_unpermitted_keys}. Context: { #{context} }", RED)
62
71
  end
63
72
  end
73
+ subscribe_log_level :unpermitted_parameters, :debug
64
74
 
65
75
  %w(write_fragment read_fragment exist_fragment? expire_fragment).each do |method|
66
76
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
77
+ # frozen_string_literal: true
67
78
  def #{method}(event)
68
- return unless logger.info? && ActionController::Base.enable_fragment_cache_logging
79
+ return unless ActionController::Base.enable_fragment_cache_logging
69
80
  key = ActiveSupport::Cache.expand_cache_key(event.payload[:key] || event.payload[:path])
70
81
  human_name = #{method.to_s.humanize.inspect}
71
82
  info("\#{human_name} \#{key} (\#{event.duration.round(1)}ms)")
72
83
  end
84
+ subscribe_log_level :#{method}, :info
73
85
  METHOD
74
86
  end
75
87
 
@@ -40,7 +40,7 @@ module ActionController # :nodoc:
40
40
  before_action(options) do
41
41
  if block_given?
42
42
  policy = current_content_security_policy
43
- yield policy
43
+ instance_exec(policy, &block)
44
44
  request.content_security_policy = policy
45
45
  end
46
46
 
@@ -4,6 +4,8 @@ require "action_controller/metal/exceptions"
4
4
  require "action_dispatch/http/content_disposition"
5
5
 
6
6
  module ActionController # :nodoc:
7
+ # = Action Controller Data \Streaming
8
+ #
7
9
  # Methods for sending arbitrary data and for streaming files to the browser,
8
10
  # instead of rendering.
9
11
  module DataStreaming
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
+ # = Action Controller Default Headers
5
+ #
4
6
  # Allows configuring default headers that will be automatically merged into
5
7
  # each response.
6
8
  module DefaultHeaders
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
+ # = Action Controller Etag With \Flash
5
+ #
4
6
  # When you're using the flash, it's generally used as a conditional on the view.
5
7
  # This means the content of the view depends on the flash. Which in turn means
6
8
  # that the ETag for a response should be computed with the content of the flash