actionpack 7.0.8.6 → 7.1.0.beta1
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 +318 -423
- 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 -27
- 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 +10 -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 +89 -50
- 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 +15 -14
- 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 +44 -15
- 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 +5 -4
- 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 +55 -33
@@ -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
|
@@ -64,7 +64,14 @@ module ActionController
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
#
|
67
|
+
# Raised when initializing Parameters with keys that aren't strings or symbols.
|
68
|
+
#
|
69
|
+
# ActionController::Parameters.new(123 => 456)
|
70
|
+
# # => ActionController::InvalidParameterKey: all keys must be Strings or Symbols, got: Integer
|
71
|
+
class InvalidParameterKey < ArgumentError
|
72
|
+
end
|
73
|
+
|
74
|
+
# = Action Controller \Parameters
|
68
75
|
#
|
69
76
|
# Allows you to choose which attributes should be permitted for mass updating
|
70
77
|
# and thus prevent accidentally exposing that which shouldn't be exposed.
|
@@ -92,8 +99,8 @@ module ActionController
|
|
92
99
|
# * +permit_all_parameters+ - If it's +true+, all the parameters will be
|
93
100
|
# permitted by default. The default is +false+.
|
94
101
|
# * +action_on_unpermitted_parameters+ - Controls behavior when parameters that are not explicitly
|
95
|
-
#
|
96
|
-
#
|
102
|
+
# permitted are found. The default value is <tt>:log</tt> in test and development environments,
|
103
|
+
# +false+ otherwise. The values can be:
|
97
104
|
# * +false+ to take no action.
|
98
105
|
# * <tt>:log</tt> to emit an <tt>ActiveSupport::Notifications.instrument</tt> event on the
|
99
106
|
# <tt>unpermitted_parameters.action_controller</tt> topic and log at the DEBUG level.
|
@@ -123,7 +130,7 @@ module ActionController
|
|
123
130
|
# environment they should only be set once at boot-time and never mutated at
|
124
131
|
# runtime.
|
125
132
|
#
|
126
|
-
# You can fetch values of
|
133
|
+
# You can fetch values of +ActionController::Parameters+ using either
|
127
134
|
# <tt>:key</tt> or <tt>"key"</tt>.
|
128
135
|
#
|
129
136
|
# params = ActionController::Parameters.new(key: "value")
|
@@ -160,12 +167,12 @@ module ActionController
|
|
160
167
|
# Returns true if the parameters have no key/value pairs.
|
161
168
|
|
162
169
|
##
|
163
|
-
# :method:
|
170
|
+
# :method: exclude?
|
164
171
|
#
|
165
172
|
# :call-seq:
|
166
|
-
#
|
173
|
+
# exclude?(key)
|
167
174
|
#
|
168
|
-
# Returns true if the given
|
175
|
+
# Returns true if the given key is not present in the parameters.
|
169
176
|
|
170
177
|
##
|
171
178
|
# :method: include?
|
@@ -191,22 +198,7 @@ module ActionController
|
|
191
198
|
#
|
192
199
|
# Returns the content of the parameters as a string.
|
193
200
|
|
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?,
|
201
|
+
delegate :keys, :empty?, :exclude?, :include?,
|
210
202
|
:as_json, :to_s, :each_key, to: :@parameters
|
211
203
|
|
212
204
|
alias_method :has_key?, :include?
|
@@ -222,13 +214,15 @@ module ActionController
|
|
222
214
|
# config.action_controller.always_permitted_parameters = %w( controller action format )
|
223
215
|
cattr_accessor :always_permitted_parameters, default: %w( controller action )
|
224
216
|
|
217
|
+
cattr_accessor :allow_deprecated_parameters_hash_equality, default: true, instance_accessor: false
|
218
|
+
|
225
219
|
class << self
|
226
220
|
def nested_attribute?(key, value) # :nodoc:
|
227
221
|
/\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
|
228
222
|
end
|
229
223
|
end
|
230
224
|
|
231
|
-
# Returns a new
|
225
|
+
# Returns a new +ActionController::Parameters+ instance.
|
232
226
|
# Also, sets the +permitted+ attribute to the default value of
|
233
227
|
# <tt>ActionController::Parameters.permit_all_parameters</tt>.
|
234
228
|
#
|
@@ -245,6 +239,12 @@ module ActionController
|
|
245
239
|
# params.permitted? # => true
|
246
240
|
# Person.new(params) # => #<Person id: nil, name: "Francesco">
|
247
241
|
def initialize(parameters = {}, logging_context = {})
|
242
|
+
parameters.each_key do |key|
|
243
|
+
unless key.is_a?(String) || key.is_a?(Symbol)
|
244
|
+
raise InvalidParameterKey, "all keys must be Strings or Symbols, got: #{key.class}"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
248
|
@parameters = parameters.with_indifferent_access
|
249
249
|
@logging_context = logging_context
|
250
250
|
@permitted = self.class.permit_all_parameters
|
@@ -256,7 +256,20 @@ module ActionController
|
|
256
256
|
if other.respond_to?(:permitted?)
|
257
257
|
permitted? == other.permitted? && parameters == other.parameters
|
258
258
|
else
|
259
|
-
|
259
|
+
if self.class.allow_deprecated_parameters_hash_equality && Hash === other
|
260
|
+
ActionController.deprecator.warn <<-WARNING.squish
|
261
|
+
Comparing equality between `ActionController::Parameters` and a
|
262
|
+
`Hash` is deprecated and will be removed in Rails 7.2. Please only do
|
263
|
+
comparisons between instances of `ActionController::Parameters`. If
|
264
|
+
you need to compare to a hash, first convert it using
|
265
|
+
`ActionController::Parameters#new`.
|
266
|
+
To disable the deprecated behavior set
|
267
|
+
`Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality = false`.
|
268
|
+
WARNING
|
269
|
+
@parameters == other
|
270
|
+
else
|
271
|
+
super
|
272
|
+
end
|
260
273
|
end
|
261
274
|
end
|
262
275
|
|
@@ -282,9 +295,9 @@ module ActionController
|
|
282
295
|
#
|
283
296
|
# safe_params = params.permit(:name)
|
284
297
|
# safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
|
285
|
-
def to_h
|
298
|
+
def to_h(&block)
|
286
299
|
if permitted?
|
287
|
-
convert_parameters_to_hashes(@parameters, :to_h)
|
300
|
+
convert_parameters_to_hashes(@parameters, :to_h, &block)
|
288
301
|
else
|
289
302
|
raise UnfilteredParameters
|
290
303
|
end
|
@@ -374,6 +387,11 @@ module ActionController
|
|
374
387
|
self
|
375
388
|
end
|
376
389
|
|
390
|
+
# Returns a new array of the values of the parameters.
|
391
|
+
def values
|
392
|
+
to_enum(:each_value).to_a
|
393
|
+
end
|
394
|
+
|
377
395
|
# Attribute that keeps track of converted arrays, if any, to avoid double
|
378
396
|
# looping in the common use case permit + mass-assignment. Defined in a
|
379
397
|
# method to instantiate it only if needed.
|
@@ -480,7 +498,7 @@ module ActionController
|
|
480
498
|
|
481
499
|
alias :required :require
|
482
500
|
|
483
|
-
# Returns a new
|
501
|
+
# Returns a new +ActionController::Parameters+ instance that
|
484
502
|
# includes only the given +filters+ and sets the +permitted+ attribute
|
485
503
|
# for the object to +true+. This is useful for limiting which attributes
|
486
504
|
# should be allowed for mass updating.
|
@@ -665,7 +683,7 @@ module ActionController
|
|
665
683
|
@parameters.dig(*keys)
|
666
684
|
end
|
667
685
|
|
668
|
-
# Returns a new
|
686
|
+
# Returns a new +ActionController::Parameters+ instance that
|
669
687
|
# includes only the given +keys+. If the given +keys+
|
670
688
|
# don't exist, returns an empty hash.
|
671
689
|
#
|
@@ -676,14 +694,14 @@ module ActionController
|
|
676
694
|
new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
|
677
695
|
end
|
678
696
|
|
679
|
-
# Returns the current
|
697
|
+
# Returns the current +ActionController::Parameters+ instance which
|
680
698
|
# contains only the given +keys+.
|
681
699
|
def slice!(*keys)
|
682
700
|
@parameters.slice!(*keys)
|
683
701
|
self
|
684
702
|
end
|
685
703
|
|
686
|
-
# Returns a new
|
704
|
+
# Returns a new +ActionController::Parameters+ instance that
|
687
705
|
# filters out the given +keys+.
|
688
706
|
#
|
689
707
|
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
|
@@ -692,6 +710,7 @@ module ActionController
|
|
692
710
|
def except(*keys)
|
693
711
|
new_instance_with_inherited_permitted_status(@parameters.except(*keys))
|
694
712
|
end
|
713
|
+
alias_method :without, :except
|
695
714
|
|
696
715
|
# Removes and returns the key/value pairs matching the given keys.
|
697
716
|
#
|
@@ -702,7 +721,7 @@ module ActionController
|
|
702
721
|
new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
|
703
722
|
end
|
704
723
|
|
705
|
-
# Returns a new
|
724
|
+
# Returns a new +ActionController::Parameters+ instance with the results of
|
706
725
|
# running +block+ once for every value. The keys are unchanged.
|
707
726
|
#
|
708
727
|
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
|
@@ -716,14 +735,14 @@ module ActionController
|
|
716
735
|
end
|
717
736
|
|
718
737
|
# Performs values transformation and returns the altered
|
719
|
-
#
|
738
|
+
# +ActionController::Parameters+ instance.
|
720
739
|
def transform_values!
|
721
740
|
return to_enum(:transform_values!) unless block_given?
|
722
741
|
@parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
|
723
742
|
self
|
724
743
|
end
|
725
744
|
|
726
|
-
# Returns a new
|
745
|
+
# Returns a new +ActionController::Parameters+ instance with the
|
727
746
|
# results of running +block+ once for every key. The values are unchanged.
|
728
747
|
def transform_keys(&block)
|
729
748
|
return to_enum(:transform_keys) unless block_given?
|
@@ -733,14 +752,14 @@ module ActionController
|
|
733
752
|
end
|
734
753
|
|
735
754
|
# Performs keys transformation and returns the altered
|
736
|
-
#
|
755
|
+
# +ActionController::Parameters+ instance.
|
737
756
|
def transform_keys!(&block)
|
738
757
|
return to_enum(:transform_keys!) unless block_given?
|
739
758
|
@parameters.transform_keys!(&block)
|
740
759
|
self
|
741
760
|
end
|
742
761
|
|
743
|
-
# Returns a new
|
762
|
+
# Returns a new +ActionController::Parameters+ instance with the
|
744
763
|
# results of running +block+ once for every key. This includes the keys
|
745
764
|
# from the root hash and from all nested hashes and arrays. The values are unchanged.
|
746
765
|
def deep_transform_keys(&block)
|
@@ -749,7 +768,7 @@ module ActionController
|
|
749
768
|
)
|
750
769
|
end
|
751
770
|
|
752
|
-
# Returns the same
|
771
|
+
# Returns the same +ActionController::Parameters+ instance with
|
753
772
|
# changed keys. This includes the keys from the root hash and from all
|
754
773
|
# nested hashes and arrays. The values are unchanged.
|
755
774
|
def deep_transform_keys!(&block)
|
@@ -765,7 +784,7 @@ module ActionController
|
|
765
784
|
convert_value_to_parameters(@parameters.delete(key, &block))
|
766
785
|
end
|
767
786
|
|
768
|
-
# Returns a new
|
787
|
+
# Returns a new +ActionController::Parameters+ instance with only
|
769
788
|
# items that the block evaluates to true.
|
770
789
|
def select(&block)
|
771
790
|
new_instance_with_inherited_permitted_status(@parameters.select(&block))
|
@@ -778,7 +797,7 @@ module ActionController
|
|
778
797
|
end
|
779
798
|
alias_method :keep_if, :select!
|
780
799
|
|
781
|
-
# Returns a new
|
800
|
+
# Returns a new +ActionController::Parameters+ instance with items
|
782
801
|
# that the block evaluates to true removed.
|
783
802
|
def reject(&block)
|
784
803
|
new_instance_with_inherited_permitted_status(@parameters.reject(&block))
|
@@ -791,7 +810,7 @@ module ActionController
|
|
791
810
|
end
|
792
811
|
alias_method :delete_if, :reject!
|
793
812
|
|
794
|
-
# Returns a new
|
813
|
+
# Returns a new +ActionController::Parameters+ instance with +nil+ values removed.
|
795
814
|
def compact
|
796
815
|
new_instance_with_inherited_permitted_status(@parameters.compact)
|
797
816
|
end
|
@@ -801,7 +820,7 @@ module ActionController
|
|
801
820
|
self if @parameters.compact!
|
802
821
|
end
|
803
822
|
|
804
|
-
# Returns a new
|
823
|
+
# Returns a new +ActionController::Parameters+ instance without the blank values.
|
805
824
|
# Uses Object#blank? for determining if a value is blank.
|
806
825
|
def compact_blank
|
807
826
|
reject { |_k, v| v.blank? }
|
@@ -813,13 +832,20 @@ module ActionController
|
|
813
832
|
reject! { |_k, v| v.blank? }
|
814
833
|
end
|
815
834
|
|
835
|
+
# Returns true if the given value is present for some key in the parameters.
|
836
|
+
def has_value?(value)
|
837
|
+
each_value.include?(convert_value_to_parameters(value))
|
838
|
+
end
|
839
|
+
|
840
|
+
alias value? has_value?
|
841
|
+
|
816
842
|
# Returns values that were assigned to the given +keys+. Note that all the
|
817
|
-
# +Hash+ objects will be converted to
|
843
|
+
# +Hash+ objects will be converted to +ActionController::Parameters+.
|
818
844
|
def values_at(*keys)
|
819
845
|
convert_value_to_parameters(@parameters.values_at(*keys))
|
820
846
|
end
|
821
847
|
|
822
|
-
# Returns a new
|
848
|
+
# Returns a new +ActionController::Parameters+ instance with all keys from
|
823
849
|
# +other_hash+ merged into current hash.
|
824
850
|
def merge(other_hash)
|
825
851
|
new_instance_with_inherited_permitted_status(
|
@@ -827,14 +853,14 @@ module ActionController
|
|
827
853
|
)
|
828
854
|
end
|
829
855
|
|
830
|
-
# Returns the current
|
856
|
+
# Returns the current +ActionController::Parameters+ instance with
|
831
857
|
# +other_hash+ merged into current hash.
|
832
858
|
def merge!(other_hash)
|
833
859
|
@parameters.merge!(other_hash.to_h)
|
834
860
|
self
|
835
861
|
end
|
836
862
|
|
837
|
-
# Returns a new
|
863
|
+
# Returns a new +ActionController::Parameters+ instance with all keys
|
838
864
|
# from current hash merged into +other_hash+.
|
839
865
|
def reverse_merge(other_hash)
|
840
866
|
new_instance_with_inherited_permitted_status(
|
@@ -843,7 +869,7 @@ module ActionController
|
|
843
869
|
end
|
844
870
|
alias_method :with_defaults, :reverse_merge
|
845
871
|
|
846
|
-
# Returns the current
|
872
|
+
# Returns the current +ActionController::Parameters+ instance with
|
847
873
|
# current hash merged into +other_hash+.
|
848
874
|
def reverse_merge!(other_hash)
|
849
875
|
@parameters.merge!(other_hash.to_h) { |key, left, right| left }
|
@@ -900,6 +926,16 @@ module ActionController
|
|
900
926
|
end
|
901
927
|
end
|
902
928
|
|
929
|
+
# Returns parameter value for the given +key+ separated by +delimiter+.
|
930
|
+
#
|
931
|
+
# params = ActionController::Parameters.new(id: "1_123", tags: "ruby,rails")
|
932
|
+
# params.extract_value(:id) # => ["1", "123"]
|
933
|
+
# params.extract_value(:tags, delimiter: ",") # => ["ruby", "rails"]
|
934
|
+
# params.extract_value(:non_existent_key) # => nil
|
935
|
+
def extract_value(key, delimiter: "_")
|
936
|
+
@parameters[key]&.split(delimiter)
|
937
|
+
end
|
938
|
+
|
903
939
|
protected
|
904
940
|
attr_reader :parameters
|
905
941
|
|
@@ -922,14 +958,15 @@ module ActionController
|
|
922
958
|
end
|
923
959
|
end
|
924
960
|
|
925
|
-
def convert_parameters_to_hashes(value, using)
|
961
|
+
def convert_parameters_to_hashes(value, using, &block)
|
926
962
|
case value
|
927
963
|
when Array
|
928
964
|
value.map { |v| convert_parameters_to_hashes(v, using) }
|
929
965
|
when Hash
|
930
|
-
value.transform_values do |v|
|
966
|
+
transformed = value.transform_values do |v|
|
931
967
|
convert_parameters_to_hashes(v, using)
|
932
|
-
end
|
968
|
+
end
|
969
|
+
(block_given? ? transformed.to_h(&block) : transformed).with_indifferent_access
|
933
970
|
when Parameters
|
934
971
|
value.send(using)
|
935
972
|
else
|
@@ -1112,6 +1149,8 @@ module ActionController
|
|
1112
1149
|
case element
|
1113
1150
|
when ->(e) { permitted_scalar?(e) }
|
1114
1151
|
sanitized << element
|
1152
|
+
when Array
|
1153
|
+
sanitized << permit_any_in_array(element)
|
1115
1154
|
when Parameters
|
1116
1155
|
sanitized << permit_any_in_parameters(element)
|
1117
1156
|
else
|
@@ -1127,7 +1166,7 @@ module ActionController
|
|
1127
1166
|
end
|
1128
1167
|
end
|
1129
1168
|
|
1130
|
-
#
|
1169
|
+
# = Strong \Parameters
|
1131
1170
|
#
|
1132
1171
|
# It provides an interface for protecting attributes from end-user
|
1133
1172
|
# 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,
|