actionpack 7.0.8 → 7.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +324 -383
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/abstract_controller/base.rb +19 -10
- data/lib/abstract_controller/caching/fragments.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +31 -6
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/helpers.rb +61 -18
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
- data/lib/abstract_controller/rendering.rb +3 -3
- data/lib/abstract_controller/translation.rb +1 -5
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +5 -3
- data/lib/action_controller/base.rb +3 -17
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +16 -4
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +2 -0
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +8 -0
- data/lib/action_controller/metal/head.rb +8 -6
- data/lib/action_controller/metal/helpers.rb +3 -14
- data/lib/action_controller/metal/http_authentication.rb +11 -4
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +8 -1
- data/lib/action_controller/metal/live.rb +24 -0
- data/lib/action_controller/metal/mime_responds.rb +2 -2
- data/lib/action_controller/metal/params_wrapper.rb +3 -1
- data/lib/action_controller/metal/permissions_policy.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +6 -6
- data/lib/action_controller/metal/renderers.rb +2 -2
- data/lib/action_controller/metal/rendering.rb +0 -7
- data/lib/action_controller/metal/request_forgery_protection.rb +138 -50
- data/lib/action_controller/metal/rescue.rb +2 -0
- data/lib/action_controller/metal/streaming.rb +70 -30
- data/lib/action_controller/metal/strong_parameters.rb +122 -52
- data/lib/action_controller/metal/url_for.rb +7 -0
- data/lib/action_controller/metal.rb +79 -21
- data/lib/action_controller/railtie.rb +22 -9
- data/lib/action_controller/renderer.rb +98 -65
- data/lib/action_controller/test_case.rb +15 -5
- data/lib/action_controller.rb +8 -1
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +1 -3
- data/lib/action_dispatch/http/content_security_policy.rb +9 -8
- data/lib/action_dispatch/http/filter_parameters.rb +11 -5
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +21 -21
- data/lib/action_dispatch/http/mime_type.rb +35 -12
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +1 -1
- data/lib/action_dispatch/http/permissions_policy.rb +39 -17
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +48 -14
- data/lib/action_dispatch/http/response.rb +78 -59
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +14 -14
- data/lib/action_dispatch/journey/route.rb +3 -2
- data/lib/action_dispatch/journey/router.rb +9 -8
- data/lib/action_dispatch/journey/routes.rb +2 -2
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
- data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +81 -98
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
- data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
- data/lib/action_dispatch/middleware/executor.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +7 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
- data/lib/action_dispatch/middleware/reloader.rb +7 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
- data/lib/action_dispatch/middleware/request_id.rb +2 -0
- data/lib/action_dispatch/middleware/server_timing.rb +4 -4
- data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +19 -15
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +7 -2
- data/lib/action_dispatch/middleware/static.rb +12 -8
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
- data/lib/action_dispatch/railtie.rb +14 -4
- data/lib/action_dispatch/request/session.rb +16 -6
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +54 -6
- data/lib/action_dispatch/routing/mapper.rb +26 -14
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +15 -6
- data/lib/action_dispatch/routing/route_set.rb +52 -22
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
- data/lib/action_dispatch/routing/url_for.rb +5 -1
- data/lib/action_dispatch/routing.rb +4 -4
- data/lib/action_dispatch/system_test_case.rb +3 -3
- data/lib/action_dispatch/system_testing/browser.rb +5 -6
- data/lib/action_dispatch/system_testing/driver.rb +13 -21
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
- data/lib/action_dispatch/testing/assertions/response.rb +13 -6
- data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
- data/lib/action_dispatch/testing/assertions.rb +3 -1
- data/lib/action_dispatch/testing/integration.rb +27 -17
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +4 -3
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -9
- data/lib/action_dispatch.rb +37 -4
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_pack.rb +1 -1
- metadata +51 -29
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController # :nodoc:
|
4
|
+
# = Action Controller \Rescue
|
5
|
+
#
|
4
6
|
# This module is responsible for providing
|
5
7
|
# {rescue_from}[rdoc-ref:ActiveSupport::Rescuable::ClassMethods#rescue_from]
|
6
8
|
# to controllers, wrapping actions to handle configured errors, and
|
@@ -1,30 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "rack/chunked"
|
4
|
-
|
5
3
|
module ActionController # :nodoc:
|
4
|
+
# = Action Controller \Streaming
|
5
|
+
#
|
6
6
|
# Allows views to be streamed back to the client as they are rendered.
|
7
7
|
#
|
8
|
-
# By default, Rails renders views by first rendering the template
|
8
|
+
# By default, \Rails renders views by first rendering the template
|
9
9
|
# and then the layout. The response is sent to the client after the whole
|
10
10
|
# template is rendered, all queries are made, and the layout is processed.
|
11
11
|
#
|
12
|
-
# Streaming inverts the rendering flow by rendering the layout first and
|
13
|
-
#
|
12
|
+
# \Streaming inverts the rendering flow by rendering the layout first and
|
13
|
+
# subsequently each part of the layout as they are processed. This allows the
|
14
14
|
# header of the HTML (which is usually in the layout) to be streamed back
|
15
|
-
# to client very quickly,
|
15
|
+
# to client very quickly, enabling JavaScripts and stylesheets to be loaded
|
16
16
|
# earlier than usual.
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# Those points are going to be addressed soon.
|
21
|
-
#
|
22
|
-
# In order to use streaming, you will need to use a Ruby version that
|
23
|
-
# supports fibers (fibers are supported since version 1.9.2 of the main
|
24
|
-
# Ruby implementation).
|
18
|
+
# Several Rack middlewares may not work and you need to be careful when streaming.
|
19
|
+
# This is covered in more detail below, see the Streaming@Middlewares section.
|
25
20
|
#
|
26
|
-
# Streaming can be added to a given template easily, all you need to do is
|
27
|
-
# to pass the +:stream+ option
|
21
|
+
# \Streaming can be added to a given template easily, all you need to do is
|
22
|
+
# to pass the +:stream+ option to +render+.
|
28
23
|
#
|
29
24
|
# class PostsController
|
30
25
|
# def index
|
@@ -35,7 +30,7 @@ module ActionController # :nodoc:
|
|
35
30
|
#
|
36
31
|
# == When to use streaming
|
37
32
|
#
|
38
|
-
# Streaming may be considered to be overkill for lightweight actions like
|
33
|
+
# \Streaming may be considered to be overkill for lightweight actions like
|
39
34
|
# +new+ or +edit+. The real benefit of streaming is on expensive actions
|
40
35
|
# that, for example, do a lot of queries on the database.
|
41
36
|
#
|
@@ -59,13 +54,13 @@ module ActionController # :nodoc:
|
|
59
54
|
# render stream: true
|
60
55
|
# end
|
61
56
|
#
|
62
|
-
# Notice that +:stream+ only works with templates. Rendering +:json+
|
57
|
+
# Notice that +:stream+ only works with templates. \Rendering +:json+
|
63
58
|
# or +:xml+ with +:stream+ won't work.
|
64
59
|
#
|
65
60
|
# == Communication between layout and template
|
66
61
|
#
|
67
62
|
# When streaming, rendering happens top-down instead of inside-out.
|
68
|
-
# Rails starts with the layout, and the template is rendered later,
|
63
|
+
# \Rails starts with the layout, and the template is rendered later,
|
69
64
|
# when its +yield+ is reached.
|
70
65
|
#
|
71
66
|
# This means that, if your application currently relies on instance
|
@@ -112,7 +107,7 @@ module ActionController # :nodoc:
|
|
112
107
|
# This means that, if you have <code>yield :title</code> in your layout
|
113
108
|
# and you want to use streaming, you would have to render the whole template
|
114
109
|
# (and eventually trigger all queries) before streaming the title and all
|
115
|
-
# assets, which
|
110
|
+
# assets, which defeats the purpose of streaming. Alternatively, you can use
|
116
111
|
# a helper called +provide+ that does the same as +content_for+ but tells the
|
117
112
|
# layout to stop searching for other entries and continue rendering.
|
118
113
|
#
|
@@ -122,7 +117,7 @@ module ActionController # :nodoc:
|
|
122
117
|
# Hello
|
123
118
|
# <%= content_for :title, " page" %>
|
124
119
|
#
|
125
|
-
#
|
120
|
+
# Resulting in:
|
126
121
|
#
|
127
122
|
# <html>
|
128
123
|
# <head><title>Main</title></head>
|
@@ -132,6 +127,8 @@ module ActionController # :nodoc:
|
|
132
127
|
# That said, when streaming, you need to properly check your templates
|
133
128
|
# and choose when to use +provide+ and +content_for+.
|
134
129
|
#
|
130
|
+
# See also ActionView::Helpers::CaptureHelper for more information.
|
131
|
+
#
|
135
132
|
# == Headers, cookies, session, and flash
|
136
133
|
#
|
137
134
|
# When streaming, the HTTP headers are sent to the client right before
|
@@ -143,10 +140,10 @@ module ActionController # :nodoc:
|
|
143
140
|
#
|
144
141
|
# Middlewares that need to manipulate the body won't work with streaming.
|
145
142
|
# You should disable those middlewares whenever streaming in development
|
146
|
-
# or production. For instance,
|
143
|
+
# or production. For instance, +Rack::Bug+ won't work when streaming as it
|
147
144
|
# needs to inject contents in the HTML body.
|
148
145
|
#
|
149
|
-
# Also
|
146
|
+
# Also +Rack::Cache+ won't work with streaming as it does not support
|
150
147
|
# streaming bodies yet. Whenever streaming +Cache-Control+ is automatically
|
151
148
|
# set to "no-cache".
|
152
149
|
#
|
@@ -156,14 +153,14 @@ module ActionController # :nodoc:
|
|
156
153
|
# happens because part of the template was already rendered and streamed to
|
157
154
|
# the client, making it impossible to render a whole exception page.
|
158
155
|
#
|
159
|
-
# Currently, when an exception happens in development or production, Rails
|
156
|
+
# Currently, when an exception happens in development or production, \Rails
|
160
157
|
# will automatically stream to the client:
|
161
158
|
#
|
162
159
|
# "><script>window.location = "/500.html"</script></html>
|
163
160
|
#
|
164
|
-
# The first two characters (">) are required in case the exception
|
165
|
-
# while rendering attributes for a given tag. You can check the real
|
166
|
-
# for the exception in your logger.
|
161
|
+
# The first two characters (<tt>"></tt>) are required in case the exception
|
162
|
+
# happens while rendering attributes for a given tag. You can check the real
|
163
|
+
# cause for the exception in your logger.
|
167
164
|
#
|
168
165
|
# == Web server support
|
169
166
|
#
|
@@ -183,16 +180,59 @@ module ActionController # :nodoc:
|
|
183
180
|
# unicorn_rails --config-file unicorn.config.rb
|
184
181
|
#
|
185
182
|
# You may also want to configure other parameters like <tt>:tcp_nodelay</tt>.
|
186
|
-
#
|
183
|
+
#
|
184
|
+
# For more information, please check the
|
185
|
+
# {documentation}[https://bogomips.org/unicorn/Unicorn/Configurator.html#method-i-listen].
|
187
186
|
#
|
188
187
|
# If you are using Unicorn with NGINX, you may need to tweak NGINX.
|
189
|
-
# Streaming should work out of the box on Rainbows.
|
188
|
+
# \Streaming should work out of the box on Rainbows.
|
190
189
|
#
|
191
190
|
# ==== Passenger
|
192
191
|
#
|
193
|
-
#
|
192
|
+
# Phusion Passenger with NGINX, offers two streaming mechanisms out of the box.
|
193
|
+
#
|
194
|
+
# 1. NGINX response buffering mechanism which is dependent on the value of
|
195
|
+
# +passenger_buffer_response+ option (default is "off").
|
196
|
+
# 2. Passenger buffering system which is always 'on' irrespective of the value
|
197
|
+
# of +passenger_buffer_response+.
|
198
|
+
#
|
199
|
+
# When +passenger_buffer_response+ is turned "on", then streaming would be
|
200
|
+
# done at the NGINX level which waits until the application is done sending
|
201
|
+
# the response back to the client.
|
202
|
+
#
|
203
|
+
# For more information, please check the
|
204
|
+
# {documentation}[https://www.phusionpassenger.com/docs/references/config_reference/nginx/#passenger_buffer_response].
|
194
205
|
#
|
195
206
|
module Streaming
|
207
|
+
class Body # :nodoc:
|
208
|
+
TERM = "\r\n"
|
209
|
+
TAIL = "0#{TERM}"
|
210
|
+
|
211
|
+
# Store the response body to be chunked.
|
212
|
+
def initialize(body)
|
213
|
+
@body = body
|
214
|
+
end
|
215
|
+
|
216
|
+
# For each element yielded by the response body, yield
|
217
|
+
# the element in chunked encoding.
|
218
|
+
def each(&block)
|
219
|
+
term = TERM
|
220
|
+
@body.each do |chunk|
|
221
|
+
size = chunk.bytesize
|
222
|
+
next if size == 0
|
223
|
+
|
224
|
+
yield [size.to_s(16), term, chunk.b, term].join
|
225
|
+
end
|
226
|
+
yield TAIL
|
227
|
+
yield term
|
228
|
+
end
|
229
|
+
|
230
|
+
# Close the response body if the response body supports it.
|
231
|
+
def close
|
232
|
+
@body.close if @body.respond_to?(:close)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
196
236
|
private
|
197
237
|
# Set proper cache control and transfer encoding when streaming
|
198
238
|
def _process_options(options)
|
@@ -211,7 +251,7 @@ module ActionController # :nodoc:
|
|
211
251
|
# Call render_body if we are streaming instead of usual +render+.
|
212
252
|
def _render_template(options)
|
213
253
|
if options.delete(:stream)
|
214
|
-
|
254
|
+
Body.new view_renderer.render_body(view_context, options)
|
215
255
|
else
|
216
256
|
super
|
217
257
|
end
|
@@ -4,6 +4,7 @@ require "active_support/core_ext/hash/indifferent_access"
|
|
4
4
|
require "active_support/core_ext/array/wrap"
|
5
5
|
require "active_support/core_ext/string/filters"
|
6
6
|
require "active_support/core_ext/object/to_query"
|
7
|
+
require "active_support/deep_mergeable"
|
7
8
|
require "action_dispatch/http/upload"
|
8
9
|
require "rack/test"
|
9
10
|
require "stringio"
|
@@ -64,7 +65,14 @@ module ActionController
|
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
67
|
-
#
|
68
|
+
# Raised when initializing Parameters with keys that aren't strings or symbols.
|
69
|
+
#
|
70
|
+
# ActionController::Parameters.new(123 => 456)
|
71
|
+
# # => ActionController::InvalidParameterKey: all keys must be Strings or Symbols, got: Integer
|
72
|
+
class InvalidParameterKey < ArgumentError
|
73
|
+
end
|
74
|
+
|
75
|
+
# = Action Controller \Parameters
|
68
76
|
#
|
69
77
|
# Allows you to choose which attributes should be permitted for mass updating
|
70
78
|
# and thus prevent accidentally exposing that which shouldn't be exposed.
|
@@ -92,8 +100,8 @@ module ActionController
|
|
92
100
|
# * +permit_all_parameters+ - If it's +true+, all the parameters will be
|
93
101
|
# permitted by default. The default is +false+.
|
94
102
|
# * +action_on_unpermitted_parameters+ - Controls behavior when parameters that are not explicitly
|
95
|
-
#
|
96
|
-
#
|
103
|
+
# permitted are found. The default value is <tt>:log</tt> in test and development environments,
|
104
|
+
# +false+ otherwise. The values can be:
|
97
105
|
# * +false+ to take no action.
|
98
106
|
# * <tt>:log</tt> to emit an <tt>ActiveSupport::Notifications.instrument</tt> event on the
|
99
107
|
# <tt>unpermitted_parameters.action_controller</tt> topic and log at the DEBUG level.
|
@@ -123,13 +131,15 @@ module ActionController
|
|
123
131
|
# environment they should only be set once at boot-time and never mutated at
|
124
132
|
# runtime.
|
125
133
|
#
|
126
|
-
# You can fetch values of
|
134
|
+
# You can fetch values of +ActionController::Parameters+ using either
|
127
135
|
# <tt>:key</tt> or <tt>"key"</tt>.
|
128
136
|
#
|
129
137
|
# params = ActionController::Parameters.new(key: "value")
|
130
138
|
# params[:key] # => "value"
|
131
139
|
# params["key"] # => "value"
|
132
140
|
class Parameters
|
141
|
+
include ActiveSupport::DeepMergeable
|
142
|
+
|
133
143
|
cattr_accessor :permit_all_parameters, instance_accessor: false, default: false
|
134
144
|
|
135
145
|
cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
|
@@ -160,12 +170,12 @@ module ActionController
|
|
160
170
|
# Returns true if the parameters have no key/value pairs.
|
161
171
|
|
162
172
|
##
|
163
|
-
# :method:
|
173
|
+
# :method: exclude?
|
164
174
|
#
|
165
175
|
# :call-seq:
|
166
|
-
#
|
176
|
+
# exclude?(key)
|
167
177
|
#
|
168
|
-
# Returns true if the given
|
178
|
+
# Returns true if the given key is not present in the parameters.
|
169
179
|
|
170
180
|
##
|
171
181
|
# :method: include?
|
@@ -191,22 +201,7 @@ module ActionController
|
|
191
201
|
#
|
192
202
|
# Returns the content of the parameters as a string.
|
193
203
|
|
194
|
-
|
195
|
-
# :method: value?
|
196
|
-
#
|
197
|
-
# :call-seq:
|
198
|
-
# value?(value)
|
199
|
-
#
|
200
|
-
# Returns true if the given value is present for some key in the parameters.
|
201
|
-
|
202
|
-
##
|
203
|
-
# :method: values
|
204
|
-
#
|
205
|
-
# :call-seq:
|
206
|
-
# values()
|
207
|
-
#
|
208
|
-
# Returns a new array of the values of the parameters.
|
209
|
-
delegate :keys, :values, :has_value?, :value?, :empty?, :include?,
|
204
|
+
delegate :keys, :empty?, :exclude?, :include?,
|
210
205
|
:as_json, :to_s, :each_key, to: :@parameters
|
211
206
|
|
212
207
|
alias_method :has_key?, :include?
|
@@ -222,13 +217,15 @@ module ActionController
|
|
222
217
|
# config.action_controller.always_permitted_parameters = %w( controller action format )
|
223
218
|
cattr_accessor :always_permitted_parameters, default: %w( controller action )
|
224
219
|
|
220
|
+
cattr_accessor :allow_deprecated_parameters_hash_equality, default: true, instance_accessor: false
|
221
|
+
|
225
222
|
class << self
|
226
223
|
def nested_attribute?(key, value) # :nodoc:
|
227
224
|
/\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
|
228
225
|
end
|
229
226
|
end
|
230
227
|
|
231
|
-
# Returns a new
|
228
|
+
# Returns a new +ActionController::Parameters+ instance.
|
232
229
|
# Also, sets the +permitted+ attribute to the default value of
|
233
230
|
# <tt>ActionController::Parameters.permit_all_parameters</tt>.
|
234
231
|
#
|
@@ -245,6 +242,12 @@ module ActionController
|
|
245
242
|
# params.permitted? # => true
|
246
243
|
# Person.new(params) # => #<Person id: nil, name: "Francesco">
|
247
244
|
def initialize(parameters = {}, logging_context = {})
|
245
|
+
parameters.each_key do |key|
|
246
|
+
unless key.is_a?(String) || key.is_a?(Symbol)
|
247
|
+
raise InvalidParameterKey, "all keys must be Strings or Symbols, got: #{key.class}"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
248
251
|
@parameters = parameters.with_indifferent_access
|
249
252
|
@logging_context = logging_context
|
250
253
|
@permitted = self.class.permit_all_parameters
|
@@ -256,7 +259,20 @@ module ActionController
|
|
256
259
|
if other.respond_to?(:permitted?)
|
257
260
|
permitted? == other.permitted? && parameters == other.parameters
|
258
261
|
else
|
259
|
-
|
262
|
+
if self.class.allow_deprecated_parameters_hash_equality && Hash === other
|
263
|
+
ActionController.deprecator.warn <<-WARNING.squish
|
264
|
+
Comparing equality between `ActionController::Parameters` and a
|
265
|
+
`Hash` is deprecated and will be removed in Rails 7.2. Please only do
|
266
|
+
comparisons between instances of `ActionController::Parameters`. If
|
267
|
+
you need to compare to a hash, first convert it using
|
268
|
+
`ActionController::Parameters#new`.
|
269
|
+
To disable the deprecated behavior set
|
270
|
+
`Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false`.
|
271
|
+
WARNING
|
272
|
+
@parameters == other
|
273
|
+
else
|
274
|
+
super
|
275
|
+
end
|
260
276
|
end
|
261
277
|
end
|
262
278
|
|
@@ -282,9 +298,9 @@ module ActionController
|
|
282
298
|
#
|
283
299
|
# safe_params = params.permit(:name)
|
284
300
|
# safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
|
285
|
-
def to_h
|
301
|
+
def to_h(&block)
|
286
302
|
if permitted?
|
287
|
-
convert_parameters_to_hashes(@parameters, :to_h)
|
303
|
+
convert_parameters_to_hashes(@parameters, :to_h, &block)
|
288
304
|
else
|
289
305
|
raise UnfilteredParameters
|
290
306
|
end
|
@@ -374,6 +390,11 @@ module ActionController
|
|
374
390
|
self
|
375
391
|
end
|
376
392
|
|
393
|
+
# Returns a new array of the values of the parameters.
|
394
|
+
def values
|
395
|
+
to_enum(:each_value).to_a
|
396
|
+
end
|
397
|
+
|
377
398
|
# Attribute that keeps track of converted arrays, if any, to avoid double
|
378
399
|
# looping in the common use case permit + mass-assignment. Defined in a
|
379
400
|
# method to instantiate it only if needed.
|
@@ -480,7 +501,7 @@ module ActionController
|
|
480
501
|
|
481
502
|
alias :required :require
|
482
503
|
|
483
|
-
# Returns a new
|
504
|
+
# Returns a new +ActionController::Parameters+ instance that
|
484
505
|
# includes only the given +filters+ and sets the +permitted+ attribute
|
485
506
|
# for the object to +true+. This is useful for limiting which attributes
|
486
507
|
# should be allowed for mass updating.
|
@@ -665,7 +686,7 @@ module ActionController
|
|
665
686
|
@parameters.dig(*keys)
|
666
687
|
end
|
667
688
|
|
668
|
-
# Returns a new
|
689
|
+
# Returns a new +ActionController::Parameters+ instance that
|
669
690
|
# includes only the given +keys+. If the given +keys+
|
670
691
|
# don't exist, returns an empty hash.
|
671
692
|
#
|
@@ -676,14 +697,14 @@ module ActionController
|
|
676
697
|
new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
|
677
698
|
end
|
678
699
|
|
679
|
-
# Returns the current
|
700
|
+
# Returns the current +ActionController::Parameters+ instance which
|
680
701
|
# contains only the given +keys+.
|
681
702
|
def slice!(*keys)
|
682
703
|
@parameters.slice!(*keys)
|
683
704
|
self
|
684
705
|
end
|
685
706
|
|
686
|
-
# Returns a new
|
707
|
+
# Returns a new +ActionController::Parameters+ instance that
|
687
708
|
# filters out the given +keys+.
|
688
709
|
#
|
689
710
|
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
|
@@ -692,6 +713,7 @@ module ActionController
|
|
692
713
|
def except(*keys)
|
693
714
|
new_instance_with_inherited_permitted_status(@parameters.except(*keys))
|
694
715
|
end
|
716
|
+
alias_method :without, :except
|
695
717
|
|
696
718
|
# Removes and returns the key/value pairs matching the given keys.
|
697
719
|
#
|
@@ -702,7 +724,7 @@ module ActionController
|
|
702
724
|
new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
|
703
725
|
end
|
704
726
|
|
705
|
-
# Returns a new
|
727
|
+
# Returns a new +ActionController::Parameters+ instance with the results of
|
706
728
|
# running +block+ once for every value. The keys are unchanged.
|
707
729
|
#
|
708
730
|
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
|
@@ -716,14 +738,14 @@ module ActionController
|
|
716
738
|
end
|
717
739
|
|
718
740
|
# Performs values transformation and returns the altered
|
719
|
-
#
|
741
|
+
# +ActionController::Parameters+ instance.
|
720
742
|
def transform_values!
|
721
743
|
return to_enum(:transform_values!) unless block_given?
|
722
744
|
@parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
|
723
745
|
self
|
724
746
|
end
|
725
747
|
|
726
|
-
# Returns a new
|
748
|
+
# Returns a new +ActionController::Parameters+ instance with the
|
727
749
|
# results of running +block+ once for every key. The values are unchanged.
|
728
750
|
def transform_keys(&block)
|
729
751
|
return to_enum(:transform_keys) unless block_given?
|
@@ -733,14 +755,14 @@ module ActionController
|
|
733
755
|
end
|
734
756
|
|
735
757
|
# Performs keys transformation and returns the altered
|
736
|
-
#
|
758
|
+
# +ActionController::Parameters+ instance.
|
737
759
|
def transform_keys!(&block)
|
738
760
|
return to_enum(:transform_keys!) unless block_given?
|
739
761
|
@parameters.transform_keys!(&block)
|
740
762
|
self
|
741
763
|
end
|
742
764
|
|
743
|
-
# Returns a new
|
765
|
+
# Returns a new +ActionController::Parameters+ instance with the
|
744
766
|
# results of running +block+ once for every key. This includes the keys
|
745
767
|
# from the root hash and from all nested hashes and arrays. The values are unchanged.
|
746
768
|
def deep_transform_keys(&block)
|
@@ -749,7 +771,7 @@ module ActionController
|
|
749
771
|
)
|
750
772
|
end
|
751
773
|
|
752
|
-
# Returns the same
|
774
|
+
# Returns the same +ActionController::Parameters+ instance with
|
753
775
|
# changed keys. This includes the keys from the root hash and from all
|
754
776
|
# nested hashes and arrays. The values are unchanged.
|
755
777
|
def deep_transform_keys!(&block)
|
@@ -765,7 +787,7 @@ module ActionController
|
|
765
787
|
convert_value_to_parameters(@parameters.delete(key, &block))
|
766
788
|
end
|
767
789
|
|
768
|
-
# Returns a new
|
790
|
+
# Returns a new +ActionController::Parameters+ instance with only
|
769
791
|
# items that the block evaluates to true.
|
770
792
|
def select(&block)
|
771
793
|
new_instance_with_inherited_permitted_status(@parameters.select(&block))
|
@@ -778,7 +800,7 @@ module ActionController
|
|
778
800
|
end
|
779
801
|
alias_method :keep_if, :select!
|
780
802
|
|
781
|
-
# Returns a new
|
803
|
+
# Returns a new +ActionController::Parameters+ instance with items
|
782
804
|
# that the block evaluates to true removed.
|
783
805
|
def reject(&block)
|
784
806
|
new_instance_with_inherited_permitted_status(@parameters.reject(&block))
|
@@ -791,7 +813,7 @@ module ActionController
|
|
791
813
|
end
|
792
814
|
alias_method :delete_if, :reject!
|
793
815
|
|
794
|
-
# Returns a new
|
816
|
+
# Returns a new +ActionController::Parameters+ instance with +nil+ values removed.
|
795
817
|
def compact
|
796
818
|
new_instance_with_inherited_permitted_status(@parameters.compact)
|
797
819
|
end
|
@@ -801,7 +823,7 @@ module ActionController
|
|
801
823
|
self if @parameters.compact!
|
802
824
|
end
|
803
825
|
|
804
|
-
# Returns a new
|
826
|
+
# Returns a new +ActionController::Parameters+ instance without the blank values.
|
805
827
|
# Uses Object#blank? for determining if a value is blank.
|
806
828
|
def compact_blank
|
807
829
|
reject { |_k, v| v.blank? }
|
@@ -813,13 +835,20 @@ module ActionController
|
|
813
835
|
reject! { |_k, v| v.blank? }
|
814
836
|
end
|
815
837
|
|
838
|
+
# Returns true if the given value is present for some key in the parameters.
|
839
|
+
def has_value?(value)
|
840
|
+
each_value.include?(convert_value_to_parameters(value))
|
841
|
+
end
|
842
|
+
|
843
|
+
alias value? has_value?
|
844
|
+
|
816
845
|
# Returns values that were assigned to the given +keys+. Note that all the
|
817
|
-
# +Hash+ objects will be converted to
|
846
|
+
# +Hash+ objects will be converted to +ActionController::Parameters+.
|
818
847
|
def values_at(*keys)
|
819
848
|
convert_value_to_parameters(@parameters.values_at(*keys))
|
820
849
|
end
|
821
850
|
|
822
|
-
# Returns a new
|
851
|
+
# Returns a new +ActionController::Parameters+ instance with all keys from
|
823
852
|
# +other_hash+ merged into current hash.
|
824
853
|
def merge(other_hash)
|
825
854
|
new_instance_with_inherited_permitted_status(
|
@@ -827,14 +856,42 @@ module ActionController
|
|
827
856
|
)
|
828
857
|
end
|
829
858
|
|
830
|
-
|
859
|
+
##
|
860
|
+
# :call-seq: merge!(other_hash)
|
861
|
+
#
|
862
|
+
# Returns the current +ActionController::Parameters+ instance with
|
831
863
|
# +other_hash+ merged into current hash.
|
832
|
-
def merge!(other_hash)
|
833
|
-
@parameters.merge!(other_hash.to_h)
|
864
|
+
def merge!(other_hash, &block)
|
865
|
+
@parameters.merge!(other_hash.to_h, &block)
|
834
866
|
self
|
835
867
|
end
|
836
868
|
|
837
|
-
|
869
|
+
##
|
870
|
+
# :method: deep_merge
|
871
|
+
# :call-seq: deep_merge(other_hash, &block)
|
872
|
+
#
|
873
|
+
# Returns a new +ActionController::Parameters+ instance with +self+ and +other_hash+ merged recursively.
|
874
|
+
#
|
875
|
+
# Like with +Hash#merge+ in the standard library, a block can be provided
|
876
|
+
# to merge values.
|
877
|
+
#
|
878
|
+
#--
|
879
|
+
# Implemented by ActiveSupport::DeepMergeable#deep_merge.
|
880
|
+
|
881
|
+
##
|
882
|
+
# :method: deep_merge!
|
883
|
+
# :call-seq: deep_merge!(other_hash, &block)
|
884
|
+
#
|
885
|
+
# Same as +#deep_merge+, but modifies +self+.
|
886
|
+
#
|
887
|
+
#--
|
888
|
+
# Implemented by ActiveSupport::DeepMergeable#deep_merge!.
|
889
|
+
|
890
|
+
def deep_merge?(other_hash) # :nodoc
|
891
|
+
other_hash.is_a?(ActiveSupport::DeepMergeable)
|
892
|
+
end
|
893
|
+
|
894
|
+
# Returns a new +ActionController::Parameters+ instance with all keys
|
838
895
|
# from current hash merged into +other_hash+.
|
839
896
|
def reverse_merge(other_hash)
|
840
897
|
new_instance_with_inherited_permitted_status(
|
@@ -843,7 +900,7 @@ module ActionController
|
|
843
900
|
end
|
844
901
|
alias_method :with_defaults, :reverse_merge
|
845
902
|
|
846
|
-
# Returns the current
|
903
|
+
# Returns the current +ActionController::Parameters+ instance with
|
847
904
|
# current hash merged into +other_hash+.
|
848
905
|
def reverse_merge!(other_hash)
|
849
906
|
@parameters.merge!(other_hash.to_h) { |key, left, right| left }
|
@@ -900,6 +957,16 @@ module ActionController
|
|
900
957
|
end
|
901
958
|
end
|
902
959
|
|
960
|
+
# Returns parameter value for the given +key+ separated by +delimiter+.
|
961
|
+
#
|
962
|
+
# params = ActionController::Parameters.new(id: "1_123", tags: "ruby,rails")
|
963
|
+
# params.extract_value(:id) # => ["1", "123"]
|
964
|
+
# params.extract_value(:tags, delimiter: ",") # => ["ruby", "rails"]
|
965
|
+
# params.extract_value(:non_existent_key) # => nil
|
966
|
+
def extract_value(key, delimiter: "_")
|
967
|
+
@parameters[key]&.split(delimiter)
|
968
|
+
end
|
969
|
+
|
903
970
|
protected
|
904
971
|
attr_reader :parameters
|
905
972
|
|
@@ -922,14 +989,15 @@ module ActionController
|
|
922
989
|
end
|
923
990
|
end
|
924
991
|
|
925
|
-
def convert_parameters_to_hashes(value, using)
|
992
|
+
def convert_parameters_to_hashes(value, using, &block)
|
926
993
|
case value
|
927
994
|
when Array
|
928
995
|
value.map { |v| convert_parameters_to_hashes(v, using) }
|
929
996
|
when Hash
|
930
|
-
value.transform_values do |v|
|
997
|
+
transformed = value.transform_values do |v|
|
931
998
|
convert_parameters_to_hashes(v, using)
|
932
|
-
end
|
999
|
+
end
|
1000
|
+
(block_given? ? transformed.to_h(&block) : transformed).with_indifferent_access
|
933
1001
|
when Parameters
|
934
1002
|
value.send(using)
|
935
1003
|
else
|
@@ -1112,6 +1180,8 @@ module ActionController
|
|
1112
1180
|
case element
|
1113
1181
|
when ->(e) { permitted_scalar?(e) }
|
1114
1182
|
sanitized << element
|
1183
|
+
when Array
|
1184
|
+
sanitized << permit_any_in_array(element)
|
1115
1185
|
when Parameters
|
1116
1186
|
sanitized << permit_any_in_parameters(element)
|
1117
1187
|
else
|
@@ -1127,7 +1197,7 @@ module ActionController
|
|
1127
1197
|
end
|
1128
1198
|
end
|
1129
1199
|
|
1130
|
-
#
|
1200
|
+
# = Strong \Parameters
|
1131
1201
|
#
|
1132
1202
|
# It provides an interface for protecting attributes from end-user
|
1133
1203
|
# assignment. This makes Action Controller parameters forbidden
|
@@ -1,6 +1,8 @@
|
|
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
|
#
|
@@ -25,6 +27,11 @@ module ActionController
|
|
25
27
|
|
26
28
|
include AbstractController::UrlFor
|
27
29
|
|
30
|
+
def initialize(...)
|
31
|
+
super
|
32
|
+
@_url_options = nil
|
33
|
+
end
|
34
|
+
|
28
35
|
def url_options
|
29
36
|
@_url_options ||= {
|
30
37
|
host: request.host,
|