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
@@ -2,10 +2,17 @@
2
2
 
3
3
  module ActionController
4
4
  module Testing
5
- extend ActiveSupport::Concern
6
-
7
5
  # Behavior specific to functional tests
8
6
  module Functional # :nodoc:
7
+ def clear_instance_variables_between_requests
8
+ if defined?(@_ivars)
9
+ new_ivars = instance_variables - @_ivars
10
+ new_ivars.each { |ivar| remove_instance_variable(ivar) }
11
+ end
12
+
13
+ @_ivars = instance_variables
14
+ end
15
+
9
16
  def recycle!
10
17
  @_url_options = nil
11
18
  self.formats = nil
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
+ # = Action Controller \UrlFor
5
+ #
4
6
  # Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing
5
7
  # the <tt>_routes</tt> method. Otherwise, an exception will be raised.
6
8
  #
7
- # In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
9
+ # In addition to AbstractController::UrlFor, this module accesses the HTTP layer to define
8
10
  # URL options like the +host+. In order to do so, this module requires the host class
9
- # to implement +env+ which needs to be Rack-compatible and +request+
10
- # which is either an instance of +ActionDispatch::Request+ or an object
11
- # that responds to the +host+, +optional_port+, +protocol+ and
12
- # +symbolized_path_parameter+ methods.
11
+ # to implement +env+ which needs to be Rack-compatible, and +request+ which
12
+ # returns an ActionDispatch::Request instance.
13
13
  #
14
14
  # class RootUrl
15
15
  # include ActionController::UrlFor
@@ -27,6 +27,11 @@ module ActionController
27
27
 
28
28
  include AbstractController::UrlFor
29
29
 
30
+ def initialize(...)
31
+ super
32
+ @_url_options = nil
33
+ end
34
+
30
35
  def url_options
31
36
  @_url_options ||= {
32
37
  host: request.host,
@@ -2,10 +2,10 @@
2
2
 
3
3
  require "active_support/core_ext/array/extract_options"
4
4
  require "action_dispatch/middleware/stack"
5
- require "action_dispatch/http/request"
6
- require "action_dispatch/http/response"
7
5
 
8
6
  module ActionController
7
+ # = Action Controller \MiddlewareStack
8
+ #
9
9
  # Extend ActionDispatch middleware stack to make it aware of options
10
10
  # allowing the following syntax in controllers:
11
11
  #
@@ -13,8 +13,8 @@ module ActionController
13
13
  # use AuthenticationMiddleware, except: [:index, :show]
14
14
  # end
15
15
  #
16
- class MiddlewareStack < ActionDispatch::MiddlewareStack #:nodoc:
17
- class Middleware < ActionDispatch::MiddlewareStack::Middleware #:nodoc:
16
+ class MiddlewareStack < ActionDispatch::MiddlewareStack # :nodoc:
17
+ class Middleware < ActionDispatch::MiddlewareStack::Middleware # :nodoc:
18
18
  def initialize(klass, args, actions, strategy, block)
19
19
  @actions = actions
20
20
  @strategy = strategy
@@ -60,9 +60,11 @@ module ActionController
60
60
  end
61
61
  end
62
62
 
63
- # <tt>ActionController::Metal</tt> is the simplest possible controller, providing a
63
+ # = Action Controller \Metal
64
+ #
65
+ # +ActionController::Metal+ is the simplest possible controller, providing a
64
66
  # valid Rack interface without the additional niceties provided by
65
- # <tt>ActionController::Base</tt>.
67
+ # ActionController::Base.
66
68
  #
67
69
  # A sample metal controller might look like this:
68
70
  #
@@ -80,9 +82,9 @@ module ActionController
80
82
  # The +action+ method returns a valid Rack application for the \Rails
81
83
  # router to dispatch to.
82
84
  #
83
- # == Rendering Helpers
85
+ # == \Rendering \Helpers
84
86
  #
85
- # <tt>ActionController::Metal</tt> by default provides no utilities for rendering
87
+ # +ActionController::Metal+ by default provides no utilities for rendering
86
88
  # views, partials, or other responses aside from explicitly calling of
87
89
  # <tt>response_body=</tt>, <tt>content_type=</tt>, and <tt>status=</tt>. To
88
90
  # add the render helpers you're used to having in a normal controller, you
@@ -98,7 +100,7 @@ module ActionController
98
100
  # end
99
101
  # end
100
102
  #
101
- # == Redirection Helpers
103
+ # == Redirection \Helpers
102
104
  #
103
105
  # To add redirection helpers to your metal controller, do the following:
104
106
  #
@@ -111,17 +113,17 @@ module ActionController
111
113
  # end
112
114
  # end
113
115
  #
114
- # == Other Helpers
116
+ # == Other \Helpers
115
117
  #
116
- # You can refer to the modules included in <tt>ActionController::Base</tt> to see
118
+ # You can refer to the modules included in ActionController::Base to see
117
119
  # other features you can bring into your metal controller.
118
120
  #
119
121
  class Metal < AbstractController::Base
120
122
  abstract!
121
123
 
122
124
  # Returns the last part of the controller's name, underscored, without the ending
123
- # <tt>Controller</tt>. For instance, PostsController returns <tt>posts</tt>.
124
- # Namespaces are left out, so Admin::PostsController returns <tt>posts</tt> as well.
125
+ # <tt>Controller</tt>. For instance, +PostsController+ returns <tt>posts</tt>.
126
+ # Namespaces are left out, so +Admin::PostsController+ returns <tt>posts</tt> as well.
125
127
  #
126
128
  # ==== Returns
127
129
  # * <tt>string</tt>
@@ -139,20 +141,53 @@ module ActionController
139
141
  false
140
142
  end
141
143
 
142
- # Delegates to the class' <tt>controller_name</tt>.
144
+ class << self
145
+ private
146
+ def inherited(subclass)
147
+ super
148
+ subclass.middleware_stack = middleware_stack.dup
149
+ subclass.class_eval do
150
+ @controller_name = nil
151
+ end
152
+ end
153
+ end
154
+
155
+ # Delegates to the class's ::controller_name.
143
156
  def controller_name
144
157
  self.class.controller_name
145
158
  end
146
159
 
147
- attr_internal :response, :request
160
+ ##
161
+ # :attr_reader: request
162
+ #
163
+ # The ActionDispatch::Request instance for the current request.
164
+ attr_internal :request
165
+
166
+ ##
167
+ # :attr_reader: response
168
+ #
169
+ # The ActionDispatch::Response instance for the current response.
170
+ attr_internal_reader :response
171
+
172
+ ##
173
+ # The ActionDispatch::Request::Session instance for the current request.
174
+ # See further details in the
175
+ # {Active Controller Session guide}[https://guides.rubyonrails.org/action_controller_overview.html#session].
148
176
  delegate :session, to: "@_request"
149
- delegate :headers, :status=, :location=, :content_type=,
177
+
178
+ ##
179
+ # Delegates to ActionDispatch::Response#headers.
180
+ delegate :headers, to: "@_response"
181
+
182
+ delegate :status=, :location=, :content_type=,
150
183
  :status, :location, :content_type, :media_type, to: "@_response"
151
184
 
152
185
  def initialize
153
186
  @_request = nil
154
187
  @_response = nil
188
+ @_response_body = nil
155
189
  @_routes = nil
190
+ @_params = nil
156
191
  super
157
192
  end
158
193
 
@@ -166,17 +201,19 @@ module ActionController
166
201
 
167
202
  alias :response_code :status # :nodoc:
168
203
 
169
- # Basic url_for that can be overridden for more robust functionality.
204
+ # Basic \url_for that can be overridden for more robust functionality.
170
205
  def url_for(string)
171
206
  string
172
207
  end
173
208
 
174
209
  def response_body=(body)
175
- body = [body] unless body.nil? || body.respond_to?(:each)
176
- response.reset_body!
177
- return unless body
178
- response.body = body
179
- super
210
+ if body
211
+ body = [body] if body.is_a?(String)
212
+ response.body = body
213
+ super
214
+ else
215
+ response.reset_body!
216
+ end
180
217
  end
181
218
 
182
219
  # Tests if render or redirect has already happened.
@@ -184,7 +221,7 @@ module ActionController
184
221
  response_body || response.committed?
185
222
  end
186
223
 
187
- def dispatch(name, request, response) #:nodoc:
224
+ def dispatch(name, request, response) # :nodoc:
188
225
  set_request!(request)
189
226
  set_response!(response)
190
227
  process(name)
@@ -193,15 +230,28 @@ module ActionController
193
230
  end
194
231
 
195
232
  def set_response!(response) # :nodoc:
233
+ if @_response
234
+ _, _, body = @_response
235
+ body.close if body.respond_to?(:close)
236
+ end
237
+
196
238
  @_response = response
197
239
  end
198
240
 
199
- def set_request!(request) #:nodoc:
241
+ # Assign the response and mark it as committed. No further processing will occur.
242
+ def response=(response)
243
+ set_response!(response)
244
+
245
+ # Force `performed?` to return true:
246
+ @_response_body = true
247
+ end
248
+
249
+ def set_request!(request) # :nodoc:
200
250
  @_request = request
201
251
  @_request.controller_instance = self
202
252
  end
203
253
 
204
- def to_a #:nodoc:
254
+ def to_a # :nodoc:
205
255
  response.to_a
206
256
  end
207
257
 
@@ -211,21 +261,26 @@ module ActionController
211
261
 
212
262
  class_attribute :middleware_stack, default: ActionController::MiddlewareStack.new
213
263
 
214
- def self.inherited(base) # :nodoc:
215
- base.middleware_stack = middleware_stack.dup
216
- super
217
- end
218
-
219
264
  class << self
220
265
  # Pushes the given Rack middleware and its arguments to the bottom of the
221
266
  # middleware stack.
222
- def use(*args, &block)
223
- middleware_stack.use(*args, &block)
267
+ def use(...)
268
+ middleware_stack.use(...)
224
269
  end
225
- ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
226
270
  end
227
271
 
228
- # Alias for +middleware_stack+.
272
+ # The middleware stack used by this controller.
273
+ #
274
+ # By default uses a variation of ActionDispatch::MiddlewareStack which
275
+ # allows for the following syntax:
276
+ #
277
+ # class PostsController < ApplicationController
278
+ # use AuthenticationMiddleware, except: [:index, :show]
279
+ # end
280
+ #
281
+ # Read more about {Rails middleware
282
+ # stack}[https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack]
283
+ # in the guides.
229
284
  def self.middleware
230
285
  middleware_stack
231
286
  end
@@ -8,11 +8,19 @@ require "action_controller/railties/helpers"
8
8
  require "action_view/railtie"
9
9
 
10
10
  module ActionController
11
- class Railtie < Rails::Railtie #:nodoc:
11
+ class Railtie < Rails::Railtie # :nodoc:
12
12
  config.action_controller = ActiveSupport::OrderedOptions.new
13
+ config.action_controller.raise_on_open_redirects = false
14
+ config.action_controller.log_query_tags_around_actions = true
15
+ config.action_controller.wrap_parameters_by_default = false
13
16
 
17
+ config.eager_load_namespaces << AbstractController
14
18
  config.eager_load_namespaces << ActionController
15
19
 
20
+ initializer "action_controller.deprecator", before: :load_environment_config do |app|
21
+ app.deprecators[:action_controller] = ActionController.deprecator
22
+ end
23
+
16
24
  initializer "action_controller.assets_config", group: :all do |app|
17
25
  app.config.action_controller.assets_dir ||= app.config.paths["public"].first
18
26
  end
@@ -25,13 +33,23 @@ module ActionController
25
33
  options = app.config.action_controller
26
34
 
27
35
  ActiveSupport.on_load(:action_controller, run_once: true) do
28
- ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
36
+ ActionController::Parameters.permit_all_parameters = options.permit_all_parameters || false
29
37
  if app.config.action_controller[:always_permitted_parameters]
30
38
  ActionController::Parameters.always_permitted_parameters =
31
- app.config.action_controller.delete(:always_permitted_parameters)
39
+ app.config.action_controller.always_permitted_parameters
32
40
  end
33
- ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
34
- (Rails.env.test? || Rails.env.development?) ? :log : false
41
+
42
+ action_on_unpermitted_parameters = options.action_on_unpermitted_parameters
43
+
44
+ if action_on_unpermitted_parameters.nil?
45
+ action_on_unpermitted_parameters = Rails.env.local? ? :log : false
46
+ end
47
+
48
+ ActionController::Parameters.action_on_unpermitted_parameters = action_on_unpermitted_parameters
49
+
50
+ unless options.allow_deprecated_parameters_hash_equality.nil?
51
+ ActionController::Parameters.allow_deprecated_parameters_hash_equality =
52
+ options.allow_deprecated_parameters_hash_equality
35
53
  end
36
54
  end
37
55
  end
@@ -55,7 +73,19 @@ module ActionController
55
73
  extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
56
74
  extend ::ActionController::Railties::Helpers
57
75
 
58
- options.each do |k, v|
76
+ wrap_parameters format: [:json] if options.wrap_parameters_by_default && respond_to?(:wrap_parameters)
77
+
78
+ # Configs used in other initializers
79
+ filtered_options = options.except(
80
+ :log_query_tags_around_actions,
81
+ :permit_all_parameters,
82
+ :action_on_unpermitted_parameters,
83
+ :always_permitted_parameters,
84
+ :wrap_parameters_by_default,
85
+ :allow_deprecated_parameters_hash_equality
86
+ )
87
+
88
+ filtered_options.each do |k, v|
59
89
  k = "#{k}="
60
90
  if respond_to?(k)
61
91
  send(k, v)
@@ -80,9 +110,36 @@ module ActionController
80
110
  end
81
111
  end
82
112
 
83
- initializer "action_controller.eager_load_actions" do
84
- ActiveSupport.on_load(:after_initialize) do
85
- ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
113
+ initializer "action_controller.query_log_tags" do |app|
114
+ query_logs_tags_enabled = app.config.respond_to?(:active_record) &&
115
+ app.config.active_record.query_log_tags_enabled &&
116
+ app.config.action_controller.log_query_tags_around_actions
117
+
118
+ if query_logs_tags_enabled
119
+ app.config.active_record.query_log_tags |= [:controller] unless app.config.active_record.query_log_tags.include?(:namespaced_controller)
120
+ app.config.active_record.query_log_tags |= [:action]
121
+
122
+ ActiveSupport.on_load(:active_record) do
123
+ ActiveRecord::QueryLogs.taggings.merge!(
124
+ controller: ->(context) { context[:controller]&.controller_name },
125
+ action: ->(context) { context[:controller]&.action_name },
126
+ namespaced_controller: ->(context) {
127
+ if context[:controller]
128
+ controller_class = context[:controller].class
129
+ # based on ActionController::Metal#controller_name, but does not demodulize
130
+ unless controller_class.anonymous?
131
+ controller_class.name.delete_suffix("Controller").underscore
132
+ end
133
+ end
134
+ }
135
+ )
136
+ end
137
+ end
138
+ end
139
+
140
+ initializer "action_controller.test_case" do |app|
141
+ ActiveSupport.on_load(:action_controller_test_case) do
142
+ ActionController::TestCase.executor_around_each_request = app.config.active_support.executor_around_test_case
86
143
  end
87
144
  end
88
145
  end
@@ -1,97 +1,127 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
- # ActionController::Renderer allows you to render arbitrary templates
5
- # without requirement of being in controller actions.
4
+ # = Action Controller \Renderer
6
5
  #
7
- # You get a concrete renderer class by invoking ActionController::Base#renderer.
8
- # For example:
6
+ # ActionController::Renderer allows you to render arbitrary templates without
7
+ # being inside a controller action.
9
8
  #
10
- # ApplicationController.renderer
11
- #
12
- # It allows you to call method #render directly.
13
- #
14
- # ApplicationController.renderer.render template: '...'
15
- #
16
- # You can use this shortcut in a controller, instead of the previous example:
17
- #
18
- # ApplicationController.render template: '...'
19
- #
20
- # #render allows you to use the same options that you can use when rendering in a controller.
21
- # For example:
9
+ # You can get a renderer instance by calling +renderer+ on a controller class:
22
10
  #
23
- # FooController.render :action, locals: { ... }, assigns: { ... }
24
- #
25
- # The template will be rendered in a Rack environment which is accessible through
26
- # ActionController::Renderer#env. You can set it up in two ways:
11
+ # ApplicationController.renderer
12
+ # PostsController.renderer
27
13
  #
28
- # * by changing renderer defaults, like
14
+ # and render a template by calling the #render method:
29
15
  #
30
- # ApplicationController.renderer.defaults # => hash with default Rack environment
16
+ # ApplicationController.renderer.render template: "posts/show", assigns: { post: Post.first }
17
+ # PostsController.renderer.render :show, assigns: { post: Post.first }
31
18
  #
32
- # * by initializing an instance of renderer by passing it a custom environment.
19
+ # As a shortcut, you can also call +render+ directly on the controller class itself:
33
20
  #
34
- # ApplicationController.renderer.new(method: 'post', https: true)
21
+ # ApplicationController.render template: "posts/show", assigns: { post: Post.first }
22
+ # PostsController.render :show, assigns: { post: Post.first }
35
23
  #
36
24
  class Renderer
37
- attr_reader :defaults, :controller
25
+ attr_reader :controller
38
26
 
39
27
  DEFAULTS = {
40
- http_host: "example.org",
41
- https: false,
42
28
  method: "get",
43
- script_name: "",
44
29
  input: ""
45
30
  }.freeze
46
31
 
47
- # Create a new renderer instance for a specific controller class.
48
- def self.for(controller, env = {}, defaults = DEFAULTS.dup)
32
+ def self.normalize_env(env) # :nodoc:
33
+ new_env = {}
34
+
35
+ env.each_pair do |key, value|
36
+ case key
37
+ when :https
38
+ value = value ? "on" : "off"
39
+ when :method
40
+ value = -value.upcase
41
+ end
42
+
43
+ key = RACK_KEY_TRANSLATION[key] || key.to_s
44
+
45
+ new_env[key] = value
46
+ end
47
+
48
+ if new_env["HTTP_HOST"]
49
+ new_env["HTTPS"] ||= "off"
50
+ new_env["SCRIPT_NAME"] ||= ""
51
+ end
52
+
53
+ if new_env["HTTPS"]
54
+ new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
55
+ end
56
+
57
+ new_env
58
+ end
59
+
60
+ # Creates a new renderer using the given controller class. See ::new.
61
+ def self.for(controller, env = nil, defaults = DEFAULTS)
49
62
  new(controller, env, defaults)
50
63
  end
51
64
 
52
- # Create a new renderer for the same controller but with a new env.
53
- def new(env = {})
54
- self.class.new controller, env, defaults
65
+ # Creates a new renderer using the same controller, but with a new Rack env.
66
+ #
67
+ # ApplicationController.renderer.new(method: "post")
68
+ #
69
+ def new(env = nil)
70
+ self.class.new controller, env, @defaults
55
71
  end
56
72
 
57
- # Create a new renderer for the same controller but with new defaults.
73
+ # Creates a new renderer using the same controller, but with the given
74
+ # defaults merged on top of the previous defaults.
58
75
  def with_defaults(defaults)
59
- self.class.new controller, @env, self.defaults.merge(defaults)
76
+ self.class.new controller, @env, @defaults.merge(defaults)
60
77
  end
61
78
 
62
- # Accepts a custom Rack environment to render templates in.
63
- # It will be merged with the default Rack environment defined by
64
- # +ActionController::Renderer::DEFAULTS+.
79
+ # Initializes a new Renderer.
80
+ #
81
+ # ==== Parameters
82
+ #
83
+ # * +controller+ - The controller class to instantiate for rendering.
84
+ # * +env+ - The Rack env to use for mocking a request when rendering.
85
+ # Entries can be typical Rack env keys and values, or they can be any of
86
+ # the following, which will be converted appropriately:
87
+ # * +:http_host+ - The HTTP host for the incoming request. Converts to
88
+ # Rack's +HTTP_HOST+.
89
+ # * +:https+ - Boolean indicating whether the incoming request uses HTTPS.
90
+ # Converts to Rack's +HTTPS+.
91
+ # * +:method+ - The HTTP method for the incoming request, case-insensitive.
92
+ # Converts to Rack's +REQUEST_METHOD+.
93
+ # * +:script_name+ - The portion of the incoming request's URL path that
94
+ # corresponds to the application. Converts to Rack's +SCRIPT_NAME+.
95
+ # * +:input+ - The input stream. Converts to Rack's +rack.input+.
96
+ # * +defaults+ - Default values for the Rack env. Entries are specified in
97
+ # the same format as +env+. +env+ will be merged on top of these values.
98
+ # +defaults+ will be retained when calling #new on a renderer instance.
99
+ #
100
+ # If no +http_host+ is specified, the env HTTP host will be derived from the
101
+ # routes' +default_url_options+. In this case, the +https+ boolean and the
102
+ # +script_name+ will also be derived from +default_url_options+ if they were
103
+ # not specified. Additionally, the +https+ boolean will fall back to
104
+ # +Rails.application.config.force_ssl+ if +default_url_options+ does not
105
+ # specify a +protocol+.
65
106
  def initialize(controller, env, defaults)
66
107
  @controller = controller
67
108
  @defaults = defaults
68
- @env = normalize_keys defaults, env
109
+ if env.blank? && @defaults == DEFAULTS
110
+ @env = DEFAULT_ENV
111
+ else
112
+ @env = normalize_env(@defaults)
113
+ @env.merge!(normalize_env(env)) unless env.blank?
114
+ end
69
115
  end
70
116
 
71
- # Render templates with any options from ActionController::Base#render_to_string.
72
- #
73
- # The primary options are:
74
- # * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
75
- # * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
76
- # It shouldn’t be used directly with unsanitized user input due to lack of validation.
77
- # * <tt>:inline</tt> - Renders an ERB template string.
78
- # * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>.
79
- # * <tt>:html</tt> - Renders the provided HTML safe string, otherwise
80
- # performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>.
81
- # * <tt>:json</tt> - Renders the provided hash or object in JSON. You don't
82
- # need to call <tt>.to_json</tt> on the object you want to render.
83
- # * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>.
84
- #
85
- # If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, then:
86
- #
87
- # If an object responding to +render_in+ is passed, +render_in+ is called on the object,
88
- # passing in the current view context.
89
- #
90
- # Otherwise, a partial is rendered using the second parameter as the locals hash.
91
- def render(*args)
92
- raise "missing controller" unless controller
117
+ def defaults
118
+ @defaults = @defaults.dup if @defaults.frozen?
119
+ @defaults
120
+ end
93
121
 
94
- request = ActionDispatch::Request.new @env
122
+ # Renders a template to a string, just like ActionController::Rendering#render_to_string.
123
+ def render(*args)
124
+ request = ActionDispatch::Request.new(env_for_request)
95
125
  request.routes = controller._routes
96
126
 
97
127
  instance = controller.new
@@ -102,19 +132,6 @@ module ActionController
102
132
  alias_method :render_to_string, :render # :nodoc:
103
133
 
104
134
  private
105
- def normalize_keys(defaults, env)
106
- new_env = {}
107
- env.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
108
-
109
- defaults.each_pair do |k, v|
110
- key = rack_key_for(k)
111
- new_env[key] = rack_value_for(k, v) unless new_env.key?(key)
112
- end
113
-
114
- new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
115
- new_env
116
- end
117
-
118
135
  RACK_KEY_TRANSLATION = {
119
136
  http_host: "HTTP_HOST",
120
137
  https: "HTTPS",
@@ -123,18 +140,15 @@ module ActionController
123
140
  input: "rack.input"
124
141
  }
125
142
 
126
- def rack_key_for(key)
127
- RACK_KEY_TRANSLATION[key] || key.to_s
128
- end
143
+ DEFAULT_ENV = normalize_env(DEFAULTS).freeze # :nodoc:
129
144
 
130
- def rack_value_for(key, value)
131
- case key
132
- when :https
133
- value ? "on" : "off"
134
- when :method
135
- -value.upcase
145
+ delegate :normalize_env, to: :class
146
+
147
+ def env_for_request
148
+ if @env.key?("HTTP_HOST") || controller._routes.nil?
149
+ @env.dup
136
150
  else
137
- value
151
+ controller._routes.default_env.merge(@env)
138
152
  end
139
153
  end
140
154
  end