actionpack 8.0.5.1 → 8.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +234 -197
  3. data/lib/abstract_controller/asset_paths.rb +4 -2
  4. data/lib/abstract_controller/base.rb +10 -2
  5. data/lib/abstract_controller/caching.rb +6 -3
  6. data/lib/abstract_controller/helpers.rb +1 -1
  7. data/lib/abstract_controller/logger.rb +2 -1
  8. data/lib/action_controller/base.rb +1 -1
  9. data/lib/action_controller/caching.rb +1 -2
  10. data/lib/action_controller/form_builder.rb +1 -1
  11. data/lib/action_controller/log_subscriber.rb +7 -0
  12. data/lib/action_controller/metal/allow_browser.rb +1 -1
  13. data/lib/action_controller/metal/conditional_get.rb +25 -0
  14. data/lib/action_controller/metal/data_streaming.rb +1 -3
  15. data/lib/action_controller/metal/exceptions.rb +5 -0
  16. data/lib/action_controller/metal/flash.rb +1 -4
  17. data/lib/action_controller/metal/head.rb +3 -1
  18. data/lib/action_controller/metal/live.rb +1 -42
  19. data/lib/action_controller/metal/permissions_policy.rb +9 -0
  20. data/lib/action_controller/metal/rate_limiting.rb +22 -7
  21. data/lib/action_controller/metal/redirecting.rb +61 -5
  22. data/lib/action_controller/metal/renderers.rb +27 -6
  23. data/lib/action_controller/metal/rendering.rb +7 -1
  24. data/lib/action_controller/metal/request_forgery_protection.rb +18 -10
  25. data/lib/action_controller/metal/rescue.rb +9 -0
  26. data/lib/action_controller/railtie.rb +2 -11
  27. data/lib/action_dispatch/http/cache.rb +111 -1
  28. data/lib/action_dispatch/http/filter_parameters.rb +5 -3
  29. data/lib/action_dispatch/http/mime_types.rb +1 -0
  30. data/lib/action_dispatch/http/param_builder.rb +28 -27
  31. data/lib/action_dispatch/http/parameters.rb +3 -3
  32. data/lib/action_dispatch/http/permissions_policy.rb +4 -0
  33. data/lib/action_dispatch/http/query_parser.rb +12 -10
  34. data/lib/action_dispatch/http/request.rb +10 -5
  35. data/lib/action_dispatch/http/response.rb +16 -3
  36. data/lib/action_dispatch/http/url.rb +99 -3
  37. data/lib/action_dispatch/journey/gtg/simulator.rb +33 -12
  38. data/lib/action_dispatch/journey/gtg/transition_table.rb +33 -43
  39. data/lib/action_dispatch/journey/nodes/node.rb +2 -1
  40. data/lib/action_dispatch/journey/route.rb +45 -31
  41. data/lib/action_dispatch/journey/router/utils.rb +8 -14
  42. data/lib/action_dispatch/journey/router.rb +59 -81
  43. data/lib/action_dispatch/journey/routes.rb +7 -0
  44. data/lib/action_dispatch/journey/visitors.rb +55 -23
  45. data/lib/action_dispatch/journey/visualizer/fsm.js +4 -6
  46. data/lib/action_dispatch/middleware/cookies.rb +4 -2
  47. data/lib/action_dispatch/middleware/debug_exceptions.rb +8 -2
  48. data/lib/action_dispatch/middleware/debug_view.rb +11 -0
  49. data/lib/action_dispatch/middleware/exception_wrapper.rb +11 -5
  50. data/lib/action_dispatch/middleware/executor.rb +12 -2
  51. data/lib/action_dispatch/middleware/public_exceptions.rb +1 -5
  52. data/lib/action_dispatch/middleware/session/cache_store.rb +17 -0
  53. data/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb +1 -0
  54. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +3 -2
  55. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +9 -5
  56. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
  57. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +1 -0
  58. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +1 -0
  59. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +50 -0
  60. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -0
  61. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -0
  62. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -0
  63. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -0
  64. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -0
  65. data/lib/action_dispatch/railtie.rb +10 -2
  66. data/lib/action_dispatch/routing/inspector.rb +4 -1
  67. data/lib/action_dispatch/routing/mapper.rb +323 -173
  68. data/lib/action_dispatch/routing/route_set.rb +2 -4
  69. data/lib/action_dispatch/routing/routes_proxy.rb +0 -1
  70. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +2 -2
  71. data/lib/action_dispatch/testing/assertions/response.rb +14 -0
  72. data/lib/action_dispatch/testing/assertions/routing.rb +11 -3
  73. data/lib/action_dispatch/testing/integration.rb +7 -7
  74. data/lib/action_dispatch/testing/request_encoder.rb +9 -9
  75. data/lib/action_pack/gem_version.rb +3 -3
  76. metadata +12 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4cafacead9b35453fc666d10a2485209e2b271f584b2b30aff8cc232ed99a92
4
- data.tar.gz: 70fd43dc74a864660b401e580067fd5d0dfdb2fb56b446a10080dabd8a868903
3
+ metadata.gz: ed45caa459109b7c6009c7b63f8be21dfe1965dc7bc745e8e7588579a9384391
4
+ data.tar.gz: aabc44311112b16f6e9b8c3f34f391d1fc1abe91cb1b0df7e920dd0068cbc8b0
5
5
  SHA512:
6
- metadata.gz: 9078e1c90c3e45687f8c1e0b815798259d414679c574eb6522e8bebda8faab18709642e29cf5a688e2601451804b116fab8039ee10bc27b2d46ff56a4ad45a5a
7
- data.tar.gz: 96fb1152a53e8f172772f0d1be0fab5feb9a511a80d421f6a0c693a8628d157426dcf0152fefefc9f091b6bd3199fb9e4571d4e13fede9da7a9e30eaf17f7966
6
+ metadata.gz: 05dc45165c2451cf7a0bd23c7b5baf55ba3e970cde0877211b208f227b98e538237c373135f5d8c3ba905c18af5834d69086ab8e223a11f7d77fed3f0e067746
7
+ data.tar.gz: 43cba6f2e00ce49bc0b4ef8172eb26b6571325dcfa5c8b5deebcec90cfad8f6d8d7d0804459dc29e5fd36073aa8f1b09348999e6258197360be3306d9c41134e
data/CHANGELOG.md CHANGED
@@ -1,323 +1,360 @@
1
- ## Rails 8.0.5.1 (July 29, 2026) ##
1
+ ## Rails 8.1.0.beta1 (September 04, 2025) ##
2
2
 
3
- * No changes.
3
+ * Remove deprecated support to a route to multiple paths.
4
4
 
5
+ *Rafael Mendonça França*
5
6
 
6
- ## Rails 8.0.5 (March 24, 2026) ##
7
-
8
- * Add `config.action_controller.live_streaming_excluded_keys` to control execution state sharing in ActionController::Live.
9
-
10
- When using ActionController::Live, actions are executed in a separate thread that shares
11
- state from the parent thread. This new configuration allows applications to opt-out specific
12
- state keys that should not be shared.
7
+ * Remove deprecated support for using semicolons as a query string separator.
13
8
 
14
- This is useful when streaming inside a `connected_to` block, where you may want
15
- the streaming thread to use its own database connection context.
9
+ Before:
16
10
 
17
11
  ```ruby
18
- # config/application.rb
19
- config.action_controller.live_streaming_excluded_keys = [:active_record_connected_to_stack]
12
+ ActionDispatch::QueryParser.each_pair("foo=bar;baz=quux").to_a
13
+ # => [["foo", "bar"], ["baz", "quux"]]
20
14
  ```
21
15
 
22
- By default, all keys are shared.
23
-
24
- *Eileen M. Uchitelle*
16
+ After:
25
17
 
18
+ ```ruby
19
+ ActionDispatch::QueryParser.each_pair("foo=bar;baz=quux").to_a
20
+ # => [["foo", "bar;baz=quux"]]
21
+ ```
26
22
 
27
- ## Rails 8.0.4.1 (March 23, 2026) ##
23
+ *Rafael Mendonça França*
28
24
 
29
- * No changes.
25
+ * Remove deprecated support to skipping over leading brackets in parameter names in the parameter parser.
30
26
 
27
+ Before:
31
28
 
32
- ## Rails 8.0.4 (October 28, 2025) ##
29
+ ```ruby
30
+ ActionDispatch::ParamBuilder.from_query_string("[foo]=bar") # => { "foo" => "bar" }
31
+ ActionDispatch::ParamBuilder.from_query_string("[foo][bar]=baz") # => { "foo" => { "bar" => "baz" } }
32
+ ```
33
33
 
34
- * Submit test requests using `as: :html` with `Content-Type: x-www-form-urlencoded`
34
+ After:
35
35
 
36
- *Sean Doyle*
36
+ ```ruby
37
+ ActionDispatch::ParamBuilder.from_query_string("[foo]=bar") # => { "[foo]" => "bar" }
38
+ ActionDispatch::ParamBuilder.from_query_string("[foo][bar]=baz") # => { "[foo]" => { "bar" => "baz" } }
39
+ ```
37
40
 
41
+ *Rafael Mendonça França*
38
42
 
39
- ## Rails 8.0.3 (September 22, 2025) ##
43
+ * Deprecate `Rails.application.config.action_dispatch.ignore_leading_brackets`.
40
44
 
41
- * URL helpers for engines mounted at the application root handle `SCRIPT_NAME` correctly.
45
+ *Rafael Mendonça França*
42
46
 
43
- Fixed an issue where `SCRIPT_NAME` is not applied to paths generated for routes in an engine
44
- mounted at "/".
47
+ * Raise `ActionController::TooManyRequests` error from `ActionController::RateLimiting`
45
48
 
46
- *Mike Dalessio*
49
+ Requests that exceed the rate limit raise an `ActionController::TooManyRequests` error.
50
+ By default, Action Dispatch rescues the error and responds with a `429 Too Many Requests` status.
47
51
 
48
- * Fix `Rails.application.reload_routes!` from clearing almost all routes.
52
+ *Sean Doyle*
49
53
 
50
- When calling `Rails.application.reload_routes!` inside a middleware of
51
- a Rake task, it was possible under certain conditions that all routes would be cleared.
52
- If ran inside a middleware, this would result in getting a 404 on most page you visit.
53
- This issue was only happening in development.
54
+ * Add .md/.markdown as Markdown extensions and add a default `markdown:` renderer:
54
55
 
55
- *Edouard Chin*
56
+ ```ruby
57
+ class Page
58
+ def to_markdown
59
+ body
60
+ end
61
+ end
56
62
 
57
- * Address `rack 3.2` deprecations warnings.
63
+ class PagesController < ActionController::Base
64
+ def show
65
+ @page = Page.find(params[:id])
58
66
 
67
+ respond_to do |format|
68
+ format.html
69
+ format.md { render markdown: @page }
70
+ end
71
+ end
72
+ end
59
73
  ```
60
- warning: Status code :unprocessable_entity is deprecated and will be removed in a future version of Rack.
61
- Please use :unprocessable_content instead.
62
- ```
63
-
64
- Rails API will transparently convert one into the other for the foreseeable future.
65
-
66
- *Earlopain*, *Jean Boussier*
67
-
68
- * Support hash-source in Content Security Policy.
69
74
 
70
- *madogiwa*
75
+ *DHH*
71
76
 
72
- * Always return empty body for HEAD requests in `PublicExceptions` and
73
- `DebugExceptions`.
77
+ * Add headers to engine routes inspection command
74
78
 
75
- This is required by `Rack::Lint` (per RFC9110).
76
-
77
- *Hartley McGuire*
79
+ *Petrik de Heus*
78
80
 
81
+ * Add "Copy as text" button to error pages
79
82
 
80
- ## Rails 8.0.2.1 (August 13, 2025) ##
83
+ *Mikkel Malmberg*
81
84
 
82
- * No changes.
85
+ * Add `scope:` option to `rate_limit` method.
83
86
 
84
- ## Rails 8.0.2 (March 12, 2025) ##
87
+ Previously, it was not possible to share a rate limit count between several controllers, since the count was by
88
+ default separate for each controller.
85
89
 
86
- * Improve `with_routing` test helper to not rebuild the middleware stack.
90
+ Now, the `scope:` option solves this problem.
87
91
 
88
- Otherwise some middleware configuration could be lost.
89
-
90
- *Édouard Chin*
91
-
92
- * Add resource name to the `ArgumentError` that's raised when invalid `:only` or `:except` options are given to `#resource` or `#resources`
92
+ ```ruby
93
+ class APIController < ActionController::API
94
+ rate_limit to: 2, within: 2.seconds, scope: "api"
95
+ end
93
96
 
94
- This makes it easier to locate the source of the problem, especially for routes drawn by gems.
97
+ class API::PostsController < APIController
98
+ # ...
99
+ end
95
100
 
96
- Before:
97
- ```
98
- :only and :except must include only [:index, :create, :new, :show, :update, :destroy, :edit], but also included [:foo, :bar]
101
+ class API::UsersController < APIController
102
+ # ...
103
+ end
99
104
  ```
100
105
 
101
- After:
102
- ```
103
- Route `resources :products` - :only and :except must include only [:index, :create, :new, :show, :update, :destroy, :edit], but also included [:foo, :bar]
104
- ```
106
+ *ArthurPV*, *Kamil Hanus*
105
107
 
106
- *Jeremy Green*
108
+ * Add support for `rack.response_finished` callbacks in ActionDispatch::Executor.
107
109
 
108
- * Fix `url_for` to handle `:path_params` gracefully when it's not a `Hash`.
110
+ The executor middleware now supports deferring completion callbacks to later
111
+ in the request lifecycle by utilizing Rack's `rack.response_finished` mechanism,
112
+ when available. This enables applications to define `rack.response_finished` callbacks
113
+ that may rely on state that would be cleaned up by the executor's completion callbacks.
109
114
 
110
- Prevents various security scanners from causing exceptions.
115
+ *Adrianna Chang*, *Hartley McGuire*
111
116
 
112
- *Martin Emde*
117
+ * Produce a log when `rescue_from` is invoked.
113
118
 
114
- * Fix `ActionDispatch::Executor` to unwrap exceptions like other error reporting middlewares.
119
+ *Steven Webb*, *Jean Boussier*
115
120
 
116
- *Jean Boussier*
121
+ * Allow hosts redirects from `hosts` Rails configuration
117
122
 
123
+ ```ruby
124
+ config.action_controller.allowed_redirect_hosts << "example.com"
125
+ ```
118
126
 
119
- ## Rails 8.0.1 (December 13, 2024) ##
127
+ *Kevin Robatel*
120
128
 
121
- * Add `ActionDispatch::Request::Session#store` method to conform Rack spec.
129
+ * `rate_limit.action_controller` notification has additional payload
122
130
 
123
- *Yaroslav*
131
+ additional values: count, to, within, by, name, cache_key
124
132
 
133
+ *Jonathan Rochkind*
125
134
 
126
- ## Rails 8.0.0.1 (December 10, 2024) ##
135
+ * Add JSON support to the built-in health controller.
127
136
 
128
- * Add validation to content security policies to disallow spaces and semicolons.
129
- Developers should use multiple arguments, and different directive methods instead.
137
+ The health controller now responds to JSON requests with a structured response
138
+ containing status and timestamp information. This makes it easier for monitoring
139
+ tools and load balancers to consume health check data programmatically.
130
140
 
131
- [CVE-2024-54133]
141
+ ```ruby
142
+ # /up.json
143
+ {
144
+ "status": "up",
145
+ "timestamp": "2025-09-19T12:00:00Z"
146
+ }
147
+ ```
132
148
 
133
- *Gannon McGibbon*
149
+ *Francesco Loreti*, *Juan Vásquez*
134
150
 
151
+ * Allow to open source file with a crash from the browser.
135
152
 
136
- ## Rails 8.0.0 (November 07, 2024) ##
153
+ *Igor Kasyanchuk*
137
154
 
138
- * No changes.
155
+ * Always check query string keys for valid encoding just like values are checked.
139
156
 
157
+ *Casper Smits*
140
158
 
141
- ## Rails 8.0.0.rc2 (October 30, 2024) ##
159
+ * Always return empty body for HEAD requests in `PublicExceptions` and
160
+ `DebugExceptions`.
142
161
 
143
- * Fix routes with `::` in the path.
162
+ This is required by `Rack::Lint` (per RFC9110).
144
163
 
145
- *Rafael Mendonça França*
164
+ *Hartley McGuire*
146
165
 
147
- * Maintain Rack 2 parameter parsing behaviour.
166
+ * Add comprehensive support for HTTP Cache-Control request directives according to RFC 9111.
148
167
 
149
- *Matthew Draper*
168
+ Provides a `request.cache_control_directives` object that gives access to request cache directives:
150
169
 
170
+ ```ruby
171
+ # Boolean directives
172
+ request.cache_control_directives.only_if_cached? # => true/false
173
+ request.cache_control_directives.no_cache? # => true/false
174
+ request.cache_control_directives.no_store? # => true/false
175
+ request.cache_control_directives.no_transform? # => true/false
176
+
177
+ # Value directives
178
+ request.cache_control_directives.max_age # => integer or nil
179
+ request.cache_control_directives.max_stale # => integer or nil (or true for valueless max-stale)
180
+ request.cache_control_directives.min_fresh # => integer or nil
181
+ request.cache_control_directives.stale_if_error # => integer or nil
182
+
183
+ # Special helpers for max-stale
184
+ request.cache_control_directives.max_stale? # => true if max-stale present (with or without value)
185
+ request.cache_control_directives.max_stale_unlimited? # => true only for valueless max-stale
186
+ ```
151
187
 
152
- ## Rails 8.0.0.rc1 (October 19, 2024) ##
188
+ Example usage:
153
189
 
154
- * Remove `Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality`.
190
+ ```ruby
191
+ def show
192
+ if request.cache_control_directives.only_if_cached?
193
+ @article = Article.find_cached(params[:id])
194
+ return head(:gateway_timeout) if @article.nil?
195
+ else
196
+ @article = Article.find(params[:id])
197
+ end
198
+
199
+ render :show
200
+ end
201
+ ```
155
202
 
156
- *Rafael Mendonça França*
203
+ *egg528*
157
204
 
158
- * Improve `ActionController::TestCase` to expose a binary encoded `request.body`.
205
+ * Add assert_in_body/assert_not_in_body as the simplest way to check if a piece of text is in the response body.
159
206
 
160
- The rack spec clearly states:
207
+ *DHH*
161
208
 
162
- > The input stream is an IO-like object which contains the raw HTTP POST data.
163
- > When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode.
209
+ * Include cookie name when calculating maximum allowed size.
164
210
 
165
- Until now its encoding was generally UTF-8, which doesn't accurately reflect production
166
- behavior.
211
+ *Hartley McGuire*
167
212
 
168
- *Jean Boussier*
213
+ * Implement `must-understand` directive according to RFC 9111.
169
214
 
170
- * Update `ActionController::AllowBrowser` to support passing method names to `:block`
215
+ The `must-understand` directive indicates that a cache must understand the semantics of the response status code, or discard the response. This directive is enforced to be used only with `no-store` to ensure proper cache behavior.
171
216
 
172
217
  ```ruby
173
- class ApplicationController < ActionController::Base
174
- allow_browser versions: :modern, block: :handle_outdated_browser
175
-
176
- private
177
- def handle_outdated_browser
178
- render file: Rails.root.join("public/custom-error.html"), status: :not_acceptable
218
+ class ArticlesController < ApplicationController
219
+ def show
220
+ @article = Article.find(params[:id])
221
+
222
+ if @article.special_format?
223
+ must_understand
224
+ render status: 203 # Non-Authoritative Information
225
+ else
226
+ fresh_when @article
179
227
  end
228
+ end
180
229
  end
181
230
  ```
182
231
 
183
- *Sean Doyle*
184
-
185
- * Raise an `ArgumentError` when invalid `:only` or `:except` options are passed into `#resource` and `#resources`.
186
-
187
- *Joshua Young*
188
-
189
- ## Rails 8.0.0.beta1 (September 26, 2024) ##
190
-
191
- * Fix non-GET requests not updating cookies in `ActionController::TestCase`.
232
+ *heka1024*
192
233
 
193
- *Jon Moss*, *Hartley McGuire*
234
+ * The JSON renderer doesn't escape HTML entities or Unicode line separators anymore.
194
235
 
195
- * Update `ActionController::Live` to use a thread-pool to reuse threads across requests.
236
+ Using `render json:` will no longer escape `<`, `>`, `&`, `U+2028` and `U+2029` characters that can cause errors
237
+ when the resulting JSON is embedded in JavaScript, or vulnerabilities when the resulting JSON is embedded in HTML.
196
238
 
197
- *Adam Renberg Tamm*
239
+ Since the renderer is used to return a JSON document as `application/json`, it's typically not necessary to escape
240
+ those characters, and it improves performance.
198
241
 
199
- * Introduce safer, more explicit params handling method with `params#expect` such that
200
- `params.expect(table: [ :attr ])` replaces `params.require(:table).permit(:attr)`
242
+ Escaping will still occur when the `:callback` option is set, since the JSON is used as JavaScript code in this
243
+ situation (JSONP).
201
244
 
202
- Ensures params are filtered with consideration for the expected
203
- types of values, improving handling of params and avoiding ignorable
204
- errors caused by params tampering.
245
+ You can use the `:escape` option or set `config.action_controller.escape_json_responses` to `true` to restore the
246
+ escaping behavior.
205
247
 
206
248
  ```ruby
207
- # If the url is altered to ?person=hacked
208
- # Before
209
- params.require(:person).permit(:name, :age, pets: [:name])
210
- # raises NoMethodError, causing a 500 and potential error reporting
211
-
212
- # After
213
- params.expect(person: [ :name, :age, pets: [[:name]] ])
214
- # raises ActionController::ParameterMissing, correctly returning a 400 error
249
+ class PostsController < ApplicationController
250
+ def index
251
+ render json: Post.last(30), escape: true
252
+ end
253
+ end
215
254
  ```
216
255
 
217
- You may also notice the new double array `[[:name]]`. In order to
218
- declare when a param is expected to be an array of parameter hashes,
219
- this new double array syntax is used to explicitly declare an array.
220
- `expect` requires you to declare expected arrays in this way, and will
221
- ignore arrays that are passed when, for example, `pet: [:name]` is used.
256
+ *Étienne Barrié*, *Jean Boussier*
222
257
 
223
- In order to preserve compatibility, `permit` does not adopt the new
224
- double array syntax and is therefore more permissive about unexpected
225
- types. Using `expect` everywhere is recommended.
258
+ * Load lazy route sets before inserting test routes
226
259
 
227
- We suggest replacing `params.require(:person).permit(:name, :age)`
228
- with the direct replacement `params.expect(person: [:name, :age])`
229
- to prevent external users from manipulating params to trigger 500
230
- errors. A 400 error will be returned instead, using public/400.html
260
+ Without loading lazy route sets early, we miss `after_routes_loaded` callbacks, or risk
261
+ invoking them with the test routes instead of the real ones if another load is triggered by an engine.
231
262
 
232
- Usage of `params.require(:id)` should likewise be replaced with
233
- `params.expect(:id)` which is designed to ensure that `params[:id]`
234
- is a scalar and not an array or hash, also requiring the param.
235
-
236
- ```ruby
237
- # Before
238
- User.find(params.require(:id)) # allows an array, altering behavior
263
+ *Gannon McGibbon*
239
264
 
240
- # After
241
- User.find(params.expect(:id)) # expect only returns non-blank permitted scalars (excludes Hash, Array, nil, "", etc)
242
- ```
265
+ * Raise `AbstractController::DoubleRenderError` if `head` is called after rendering.
243
266
 
244
- *Martin Emde*
267
+ After this change, invoking `head` will lead to an error if response body is already set:
245
268
 
246
- * System Testing: Disable Chrome's search engine choice by default in system tests.
269
+ ```ruby
270
+ class PostController < ApplicationController
271
+ def index
272
+ render locals: {}
273
+ head :ok
274
+ end
275
+ end
276
+ ```
247
277
 
248
- *glaszig*
278
+ *Iaroslav Kurbatov*
249
279
 
250
- * Fix `Request#raw_post` raising `NoMethodError` when `rack.input` is `nil`.
280
+ * The Cookie Serializer can now serialize an Active Support SafeBuffer when using message pack.
251
281
 
252
- *Hartley McGuire*
282
+ Such code would previously produce an error if an application was using messagepack as its cookie serializer.
253
283
 
254
- * Remove `racc` dependency by manually writing `ActionDispatch::Journey::Scanner`.
284
+ ```ruby
285
+ class PostController < ApplicationController
286
+ def index
287
+ flash.notice = t(:hello_html) # This would try to serialize a SafeBuffer, which was not possible.
288
+ end
289
+ end
290
+ ```
255
291
 
256
- *Gannon McGibbon*
292
+ *Edouard Chin*
257
293
 
258
- * Speed up `ActionDispatch::Routing::Mapper::Scope#[]` by merging frame hashes.
294
+ * Fix `Rails.application.reload_routes!` from clearing almost all routes.
259
295
 
260
- *Gannon McGibbon*
296
+ When calling `Rails.application.reload_routes!` inside a middleware of
297
+ a Rake task, it was possible under certain conditions that all routes would be cleared.
298
+ If ran inside a middleware, this would result in getting a 404 on most page you visit.
299
+ This issue was only happening in development.
261
300
 
262
- * Allow bots to ignore `allow_browser`.
301
+ *Edouard Chin*
263
302
 
264
- *Matthew Nguyen*
303
+ * Add resource name to the `ArgumentError` that's raised when invalid `:only` or `:except` options are given to `#resource` or `#resources`
265
304
 
266
- * Deprecate drawing routes with multiple paths to make routing faster.
267
- You may use `with_options` or a loop to make drawing multiple paths easier.
305
+ This makes it easier to locate the source of the problem, especially for routes drawn by gems.
268
306
 
269
- ```ruby
270
- # Before
271
- get "/users", "/other_path", to: "users#index"
307
+ Before:
308
+ ```
309
+ :only and :except must include only [:index, :create, :new, :show, :update, :destroy, :edit], but also included [:foo, :bar]
310
+ ```
272
311
 
273
- # After
274
- get "/users", to: "users#index"
275
- get "/other_path", to: "users#index"
312
+ After:
313
+ ```
314
+ Route `resources :products` - :only and :except must include only [:index, :create, :new, :show, :update, :destroy, :edit], but also included [:foo, :bar]
276
315
  ```
277
316
 
278
- *Gannon McGibbon*
317
+ *Jeremy Green*
279
318
 
280
- * Make `http_cache_forever` use `immutable: true`
319
+ * A route pointing to a non-existing controller now returns a 500 instead of a 404.
281
320
 
282
- *Nate Matykiewicz*
321
+ A controller not existing isn't a routing error that should result
322
+ in a 404, but a programming error that should result in a 500 and
323
+ be reported.
283
324
 
284
- * Add `config.action_dispatch.strict_freshness`.
325
+ Until recently, this was hard to untangle because of the support
326
+ for dynamic `:controller` segment in routes, but since this is
327
+ deprecated and will be removed in Rails 8.1, we can now easily
328
+ not consider missing controllers as routing errors.
285
329
 
286
- When set to `true`, the `ETag` header takes precedence over the `Last-Modified` header when both are present,
287
- as specified by RFC 7232, Section 6.
330
+ *Jean Boussier*
288
331
 
289
- Defaults to `false` to maintain compatibility with previous versions of Rails, but is enabled as part of
290
- Rails 8.0 defaults.
332
+ * Add `check_collisions` option to `ActionDispatch::Session::CacheStore`.
291
333
 
292
- *heka1024*
334
+ Newly generated session ids use 128 bits of randomness, which is more than
335
+ enough to ensure collisions can't happen, but if you need to harden sessions
336
+ even more, you can enable this option to check in the session store that the id
337
+ is indeed free you can enable that option. This however incurs an extra write
338
+ on session creation.
293
339
 
294
- * Support `immutable` directive in Cache-Control
340
+ *Shia*
295
341
 
296
- ```ruby
297
- expires_in 1.minute, public: true, immutable: true
298
- # Cache-Control: public, max-age=60, immutable
299
- ```
342
+ * In ExceptionWrapper, match backtrace lines with built templates more often,
343
+ allowing improved highlighting of errors within do-end blocks in templates.
344
+ Fix for Ruby 3.4 to match new method labels in backtrace.
300
345
 
301
- *heka1024*
346
+ *Martin Emde*
302
347
 
303
- * Add `:wasm_unsafe_eval` mapping for `content_security_policy`
348
+ * Allow setting content type with a symbol of the Mime type.
304
349
 
305
350
  ```ruby
306
351
  # Before
307
- policy.script_src "'wasm-unsafe-eval'"
352
+ response.content_type = "text/html"
308
353
 
309
354
  # After
310
- policy.script_src :wasm_unsafe_eval
355
+ response.content_type = :html
311
356
  ```
312
357
 
313
- *Joe Haig*
314
-
315
- * Add `display_capture` and `keyboard_map` in `permissions_policy`
316
-
317
- *Cyril Blaecke*
318
-
319
- * Add `connect` route helper.
320
-
321
- *Samuel Williams*
358
+ *Petrik de Heus*
322
359
 
323
- Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/actionpack/CHANGELOG.md) for previous changes.
360
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/actionpack/CHANGELOG.md) for previous changes.
@@ -7,8 +7,10 @@ module AbstractController
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- config_accessor :asset_host, :assets_dir, :javascripts_dir,
11
- :stylesheets_dir, :default_asset_host_protocol, :relative_url_root
10
+ singleton_class.delegate :asset_host, :asset_host=, :assets_dir, :assets_dir=, :javascripts_dir, :javascripts_dir=,
11
+ :stylesheets_dir, :stylesheets_dir=, :default_asset_host_protocol, :default_asset_host_protocol=, :relative_url_root, :relative_url_root=, to: :config
12
+ delegate :asset_host, :asset_host=, :assets_dir, :assets_dir=, :javascripts_dir, :javascripts_dir=,
13
+ :stylesheets_dir, :stylesheets_dir=, :default_asset_host_protocol, :default_asset_host_protocol=, :relative_url_root, :relative_url_root=, to: :config
12
14
  end
13
15
  end
14
16
  end
@@ -3,7 +3,6 @@
3
3
  # :markup: markdown
4
4
 
5
5
  require "abstract_controller/error"
6
- require "active_support/configurable"
7
6
  require "active_support/descendants_tracker"
8
7
  require "active_support/core_ext/module/anonymous"
9
8
  require "active_support/core_ext/module/attr_internal"
@@ -47,7 +46,7 @@ module AbstractController
47
46
  # Returns the formats that can be processed by the controller.
48
47
  attr_internal :formats
49
48
 
50
- include ActiveSupport::Configurable
49
+ class_attribute :config, instance_predicate: false, default: ActiveSupport::OrderedOptions.new
51
50
  extend ActiveSupport::DescendantsTracker
52
51
 
53
52
  class << self
@@ -65,6 +64,7 @@ module AbstractController
65
64
  unless klass.instance_variable_defined?(:@abstract)
66
65
  klass.instance_variable_set(:@abstract, false)
67
66
  end
67
+ klass.config = ActiveSupport::InheritableOptions.new(config)
68
68
  super
69
69
  end
70
70
 
@@ -121,6 +121,10 @@ module AbstractController
121
121
  @controller_path ||= name.delete_suffix("Controller").underscore unless anonymous?
122
122
  end
123
123
 
124
+ def configure # :nodoc:
125
+ yield config
126
+ end
127
+
124
128
  # Refresh the cached action_methods when a new action_method is added.
125
129
  def method_added(name)
126
130
  super
@@ -190,6 +194,10 @@ module AbstractController
190
194
  true
191
195
  end
192
196
 
197
+ def config # :nodoc:
198
+ @_config ||= self.class.config.inheritable_copy
199
+ end
200
+
193
201
  def inspect # :nodoc:
194
202
  "#<#{self.class.name}:#{'%#016x' % (object_id << 1)}>"
195
203
  end
@@ -32,13 +32,16 @@ module AbstractController
32
32
  included do
33
33
  extend ConfigMethods
34
34
 
35
- config_accessor :default_static_extension
35
+ singleton_class.delegate :default_static_extension, :default_static_extension=, to: :config
36
+ delegate :default_static_extension, :default_static_extension=, to: :config
36
37
  self.default_static_extension ||= ".html"
37
38
 
38
- config_accessor :perform_caching
39
+ singleton_class.delegate :perform_caching, :perform_caching=, to: :config
40
+ delegate :perform_caching, :perform_caching=, to: :config
39
41
  self.perform_caching = true if perform_caching.nil?
40
42
 
41
- config_accessor :enable_fragment_cache_logging
43
+ singleton_class.delegate :enable_fragment_cache_logging, :enable_fragment_cache_logging=, to: :config
44
+ delegate :enable_fragment_cache_logging, :enable_fragment_cache_logging=, to: :config
42
45
  self.enable_fragment_cache_logging = false
43
46
 
44
47
  class_attribute :_view_cache_dependencies, default: []