actionpack 6.1.7.5 → 7.1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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