actionpack 5.2.0 → 6.1.4
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 +408 -190
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/abstract_controller/base.rb +38 -4
- data/lib/abstract_controller/caching/fragments.rb +6 -22
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +14 -2
- data/lib/abstract_controller/collector.rb +1 -2
- data/lib/abstract_controller/helpers.rb +106 -90
- data/lib/abstract_controller/railties/routes_helpers.rb +17 -1
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +11 -5
- data/lib/abstract_controller.rb +2 -0
- data/lib/action_controller/api.rb +4 -3
- data/lib/action_controller/base.rb +6 -9
- data/lib/action_controller/caching.rb +1 -3
- data/lib/action_controller/log_subscriber.rb +10 -7
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/conditional_get.rb +19 -5
- data/lib/action_controller/metal/content_security_policy.rb +1 -2
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +6 -7
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +4 -6
- data/lib/action_controller/metal/exceptions.rb +56 -2
- data/lib/action_controller/metal/flash.rb +5 -5
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +14 -5
- data/lib/action_controller/metal/http_authentication.rb +25 -24
- data/lib/action_controller/metal/implicit_render.rb +5 -15
- data/lib/action_controller/metal/instrumentation.rb +13 -14
- data/lib/action_controller/metal/live.rb +39 -32
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +19 -4
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +33 -23
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +7 -7
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +8 -3
- data/lib/action_controller/metal/request_forgery_protection.rb +89 -36
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/streaming.rb +0 -1
- data/lib/action_controller/metal/strong_parameters.rb +181 -69
- data/lib/action_controller/metal/url_for.rb +1 -1
- data/lib/action_controller/metal.rb +12 -10
- data/lib/action_controller/railties/helpers.rb +1 -1
- data/lib/action_controller/renderer.rb +37 -13
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +81 -70
- data/lib/action_controller.rb +7 -4
- data/lib/action_dispatch/http/cache.rb +34 -28
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +47 -24
- data/lib/action_dispatch/http/filter_parameters.rb +9 -8
- data/lib/action_dispatch/http/filter_redirect.rb +2 -3
- data/lib/action_dispatch/http/headers.rb +4 -4
- data/lib/action_dispatch/http/mime_negotiation.rb +31 -13
- data/lib/action_dispatch/http/mime_type.rb +43 -24
- data/lib/action_dispatch/http/parameters.rb +14 -23
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +45 -22
- data/lib/action_dispatch/http/response.rb +45 -25
- data/lib/action_dispatch/http/upload.rb +9 -1
- data/lib/action_dispatch/http/url.rb +82 -82
- data/lib/action_dispatch/journey/formatter.rb +55 -31
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -37
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -5
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +13 -11
- data/lib/action_dispatch/journey/parser.rb +13 -13
- data/lib/action_dispatch/journey/parser.y +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +21 -22
- data/lib/action_dispatch/journey/route.rb +10 -20
- data/lib/action_dispatch/journey/router/utils.rb +14 -12
- data/lib/action_dispatch/journey/router.rb +26 -34
- data/lib/action_dispatch/journey/routes.rb +1 -2
- data/lib/action_dispatch/journey/scanner.rb +10 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -4
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +128 -109
- data/lib/action_dispatch/middleware/debug_exceptions.rb +43 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
- data/lib/action_dispatch/middleware/debug_view.rb +66 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -30
- data/lib/action_dispatch/middleware/flash.rb +2 -2
- data/lib/action_dispatch/middleware/host_authorization.rb +130 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +14 -16
- data/lib/action_dispatch/middleware/request_id.rb +5 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +15 -2
- data/lib/action_dispatch/middleware/session/cache_store.rb +11 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +24 -19
- data/lib/action_dispatch/middleware/show_exceptions.rb +3 -2
- data/lib/action_dispatch/middleware/ssl.rb +20 -15
- data/lib/action_dispatch/middleware/stack.rb +57 -3
- data/lib/action_dispatch/middleware/static.rb +153 -93
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +6 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +4 -1
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +104 -8
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +24 -1
- data/lib/action_dispatch/railtie.rb +8 -2
- data/lib/action_dispatch/request/session.rb +17 -10
- data/lib/action_dispatch/request/utils.rb +28 -2
- data/lib/action_dispatch/routing/inspector.rb +101 -53
- data/lib/action_dispatch/routing/mapper.rb +156 -103
- data/lib/action_dispatch/routing/polymorphic_routes.rb +21 -19
- data/lib/action_dispatch/routing/redirection.rb +4 -4
- data/lib/action_dispatch/routing/route_set.rb +71 -69
- data/lib/action_dispatch/routing/url_for.rb +3 -3
- data/lib/action_dispatch/routing.rb +21 -20
- data/lib/action_dispatch/system_test_case.rb +54 -11
- data/lib/action_dispatch/system_testing/browser.rb +53 -16
- data/lib/action_dispatch/system_testing/driver.rb +11 -3
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +49 -7
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -6
- data/lib/action_dispatch/testing/assertion_response.rb +0 -1
- data/lib/action_dispatch/testing/assertions/response.rb +4 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/integration.rb +61 -28
- data/lib/action_dispatch/testing/request_encoder.rb +3 -3
- data/lib/action_dispatch/testing/test_process.rb +29 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -32
- data/lib/action_dispatch.rb +14 -7
- data/lib/action_pack/gem_version.rb +3 -3
- data/lib/action_pack.rb +1 -1
- metadata +39 -22
- data/lib/action_controller/metal/force_ssl.rb +0 -99
- data/lib/action_dispatch/http/parameter_filter.rb +0 -86
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/hash/indifferent_access"
|
4
|
-
require "active_support/core_ext/hash/transform_values"
|
5
4
|
require "active_support/core_ext/array/wrap"
|
6
5
|
require "active_support/core_ext/string/filters"
|
7
6
|
require "active_support/core_ext/object/to_query"
|
8
|
-
require "active_support/rescuable"
|
9
7
|
require "action_dispatch/http/upload"
|
10
8
|
require "rack/test"
|
11
9
|
require "stringio"
|
@@ -21,12 +19,36 @@ module ActionController
|
|
21
19
|
# params.require(:a)
|
22
20
|
# # => ActionController::ParameterMissing: param is missing or the value is empty: a
|
23
21
|
class ParameterMissing < KeyError
|
24
|
-
attr_reader :param # :nodoc:
|
22
|
+
attr_reader :param, :keys # :nodoc:
|
25
23
|
|
26
|
-
def initialize(param) # :nodoc:
|
24
|
+
def initialize(param, keys = nil) # :nodoc:
|
27
25
|
@param = param
|
26
|
+
@keys = keys
|
28
27
|
super("param is missing or the value is empty: #{param}")
|
29
28
|
end
|
29
|
+
|
30
|
+
class Correction
|
31
|
+
def initialize(error)
|
32
|
+
@error = error
|
33
|
+
end
|
34
|
+
|
35
|
+
def corrections
|
36
|
+
if @error.param && @error.keys
|
37
|
+
maybe_these = @error.keys
|
38
|
+
|
39
|
+
maybe_these.sort_by { |n|
|
40
|
+
DidYouMean::Jaro.distance(@error.param.to_s, n)
|
41
|
+
}.reverse.first(4)
|
42
|
+
else
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# We may not have DYM, and DYM might not let us register error handlers
|
49
|
+
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
50
|
+
DidYouMean.correct_error(self, Correction)
|
51
|
+
end
|
30
52
|
end
|
31
53
|
|
32
54
|
# Raised when a supplied parameter is not expected and
|
@@ -59,7 +81,7 @@ module ActionController
|
|
59
81
|
|
60
82
|
# == Action Controller \Parameters
|
61
83
|
#
|
62
|
-
# Allows you to choose which attributes should be
|
84
|
+
# Allows you to choose which attributes should be permitted for mass updating
|
63
85
|
# and thus prevent accidentally exposing that which shouldn't be exposed.
|
64
86
|
# Provides two methods for this purpose: #require and #permit. The former is
|
65
87
|
# used to mark parameters as required. The latter is used to set the parameter
|
@@ -133,6 +155,15 @@ module ActionController
|
|
133
155
|
#
|
134
156
|
# Returns a hash that can be used as the JSON representation for the parameters.
|
135
157
|
|
158
|
+
##
|
159
|
+
# :method: each_key
|
160
|
+
#
|
161
|
+
# :call-seq:
|
162
|
+
# each_key()
|
163
|
+
#
|
164
|
+
# Calls block once for each key in the parameters, passing the key.
|
165
|
+
# If no block is given, an enumerator is returned instead.
|
166
|
+
|
136
167
|
##
|
137
168
|
# :method: empty?
|
138
169
|
#
|
@@ -173,6 +204,14 @@ module ActionController
|
|
173
204
|
#
|
174
205
|
# Returns true if the given key is present in the parameters.
|
175
206
|
|
207
|
+
##
|
208
|
+
# :method: member?
|
209
|
+
#
|
210
|
+
# :call-seq:
|
211
|
+
# member?(key)
|
212
|
+
#
|
213
|
+
# Returns true if the given key is present in the parameters.
|
214
|
+
|
176
215
|
##
|
177
216
|
# :method: keys
|
178
217
|
#
|
@@ -204,8 +243,8 @@ module ActionController
|
|
204
243
|
# values()
|
205
244
|
#
|
206
245
|
# Returns a new array of the values of the parameters.
|
207
|
-
delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?,
|
208
|
-
:as_json, :to_s, to: :@parameters
|
246
|
+
delegate :keys, :key?, :has_key?, :member?, :values, :has_value?, :value?, :empty?, :include?,
|
247
|
+
:as_json, :to_s, :each_key, to: :@parameters
|
209
248
|
|
210
249
|
# By default, never raise an UnpermittedParameters exception if these
|
211
250
|
# params are present. The default includes both 'controller' and 'action'
|
@@ -213,9 +252,15 @@ module ActionController
|
|
213
252
|
# to change these is to specify `always_permitted_parameters` in your
|
214
253
|
# config. For instance:
|
215
254
|
#
|
216
|
-
# config.always_permitted_parameters = %w( controller action format )
|
255
|
+
# config.action_controller.always_permitted_parameters = %w( controller action format )
|
217
256
|
cattr_accessor :always_permitted_parameters, default: %w( controller action )
|
218
257
|
|
258
|
+
class << self
|
259
|
+
def nested_attribute?(key, value) # :nodoc:
|
260
|
+
/\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
219
264
|
# Returns a new instance of <tt>ActionController::Parameters</tt>.
|
220
265
|
# Also, sets the +permitted+ attribute to the default value of
|
221
266
|
# <tt>ActionController::Parameters.permit_all_parameters</tt>.
|
@@ -246,6 +291,11 @@ module ActionController
|
|
246
291
|
@parameters == other
|
247
292
|
end
|
248
293
|
end
|
294
|
+
alias eql? ==
|
295
|
+
|
296
|
+
def hash
|
297
|
+
[@parameters.hash, @permitted].hash
|
298
|
+
end
|
249
299
|
|
250
300
|
# Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
|
251
301
|
# representation of the parameters with all unpermitted keys removed.
|
@@ -334,12 +384,26 @@ module ActionController
|
|
334
384
|
# Convert all hashes in values into parameters, then yield each pair in
|
335
385
|
# the same way as <tt>Hash#each_pair</tt>.
|
336
386
|
def each_pair(&block)
|
387
|
+
return to_enum(__callee__) unless block_given?
|
337
388
|
@parameters.each_pair do |key, value|
|
338
389
|
yield [key, convert_hashes_to_parameters(key, value)]
|
339
390
|
end
|
391
|
+
|
392
|
+
self
|
340
393
|
end
|
341
394
|
alias_method :each, :each_pair
|
342
395
|
|
396
|
+
# Convert all hashes in values into parameters, then yield each value in
|
397
|
+
# the same way as <tt>Hash#each_value</tt>.
|
398
|
+
def each_value(&block)
|
399
|
+
return to_enum(:each_value) unless block_given?
|
400
|
+
@parameters.each_pair do |key, value|
|
401
|
+
yield convert_hashes_to_parameters(key, value)
|
402
|
+
end
|
403
|
+
|
404
|
+
self
|
405
|
+
end
|
406
|
+
|
343
407
|
# Attribute that keeps track of converted arrays, if any, to avoid double
|
344
408
|
# looping in the common use case permit + mass-assignment. Defined in a
|
345
409
|
# method to instantiate it only if needed.
|
@@ -375,7 +439,7 @@ module ActionController
|
|
375
439
|
# Person.new(params) # => #<Person id: nil, name: "Francesco">
|
376
440
|
def permit!
|
377
441
|
each_pair do |key, value|
|
378
|
-
Array.wrap(value).each do |v|
|
442
|
+
Array.wrap(value).flatten.each do |v|
|
379
443
|
v.permit! if v.respond_to? :permit!
|
380
444
|
end
|
381
445
|
end
|
@@ -440,7 +504,7 @@ module ActionController
|
|
440
504
|
if value.present? || value == false
|
441
505
|
value
|
442
506
|
else
|
443
|
-
raise ParameterMissing.new(key)
|
507
|
+
raise ParameterMissing.new(key, @parameters.keys)
|
444
508
|
end
|
445
509
|
end
|
446
510
|
|
@@ -506,7 +570,7 @@ module ActionController
|
|
506
570
|
#
|
507
571
|
# Note that if you use +permit+ in a key that points to a hash,
|
508
572
|
# it won't allow all the hash. You also need to specify which
|
509
|
-
# attributes inside the hash should be
|
573
|
+
# attributes inside the hash should be permitted.
|
510
574
|
#
|
511
575
|
# params = ActionController::Parameters.new({
|
512
576
|
# person: {
|
@@ -561,12 +625,14 @@ module ActionController
|
|
561
625
|
# Returns a parameter for the given +key+. If the +key+
|
562
626
|
# can't be found, there are several options: With no other arguments,
|
563
627
|
# it will raise an <tt>ActionController::ParameterMissing</tt> error;
|
564
|
-
# if
|
628
|
+
# if a second argument is given, then that is returned (converted to an
|
629
|
+
# instance of ActionController::Parameters if possible); if a block
|
565
630
|
# is given, then that will be run and its result returned.
|
566
631
|
#
|
567
632
|
# params = ActionController::Parameters.new(person: { name: "Francesco" })
|
568
633
|
# params.fetch(:person) # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
|
569
634
|
# params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none
|
635
|
+
# params.fetch(:none, {}) # => <ActionController::Parameters {} permitted: false>
|
570
636
|
# params.fetch(:none, "Francesco") # => "Francesco"
|
571
637
|
# params.fetch(:none) { "Francesco" } # => "Francesco"
|
572
638
|
def fetch(key, *args)
|
@@ -575,25 +641,24 @@ module ActionController
|
|
575
641
|
if block_given?
|
576
642
|
yield
|
577
643
|
else
|
578
|
-
args.fetch(0) { raise ActionController::ParameterMissing.new(key) }
|
644
|
+
args.fetch(0) { raise ActionController::ParameterMissing.new(key, @parameters.keys) }
|
579
645
|
end
|
580
646
|
}
|
581
647
|
)
|
582
648
|
end
|
583
649
|
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
end
|
650
|
+
# Extracts the nested parameter from the given +keys+ by calling +dig+
|
651
|
+
# at each step. Returns +nil+ if any intermediate step is +nil+.
|
652
|
+
#
|
653
|
+
# params = ActionController::Parameters.new(foo: { bar: { baz: 1 } })
|
654
|
+
# params.dig(:foo, :bar, :baz) # => 1
|
655
|
+
# params.dig(:foo, :zot, :xyz) # => nil
|
656
|
+
#
|
657
|
+
# params2 = ActionController::Parameters.new(foo: [10, 11, 12])
|
658
|
+
# params2.dig(:foo, 1) # => 11
|
659
|
+
def dig(*keys)
|
660
|
+
convert_hashes_to_parameters(keys.first, @parameters[keys.first])
|
661
|
+
@parameters.dig(*keys)
|
597
662
|
end
|
598
663
|
|
599
664
|
# Returns a new <tt>ActionController::Parameters</tt> instance that
|
@@ -639,42 +704,55 @@ module ActionController
|
|
639
704
|
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
|
640
705
|
# params.transform_values { |x| x * 2 }
|
641
706
|
# # => <ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
|
642
|
-
def transform_values
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
else
|
648
|
-
@parameters.transform_values
|
649
|
-
end
|
707
|
+
def transform_values
|
708
|
+
return to_enum(:transform_values) unless block_given?
|
709
|
+
new_instance_with_inherited_permitted_status(
|
710
|
+
@parameters.transform_values { |v| yield convert_value_to_parameters(v) }
|
711
|
+
)
|
650
712
|
end
|
651
713
|
|
652
714
|
# Performs values transformation and returns the altered
|
653
715
|
# <tt>ActionController::Parameters</tt> instance.
|
654
|
-
def transform_values!
|
655
|
-
|
716
|
+
def transform_values!
|
717
|
+
return to_enum(:transform_values!) unless block_given?
|
718
|
+
@parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
|
656
719
|
self
|
657
720
|
end
|
658
721
|
|
659
722
|
# Returns a new <tt>ActionController::Parameters</tt> instance with the
|
660
723
|
# results of running +block+ once for every key. The values are unchanged.
|
661
724
|
def transform_keys(&block)
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
else
|
667
|
-
@parameters.transform_keys
|
668
|
-
end
|
725
|
+
return to_enum(:transform_keys) unless block_given?
|
726
|
+
new_instance_with_inherited_permitted_status(
|
727
|
+
@parameters.transform_keys(&block)
|
728
|
+
)
|
669
729
|
end
|
670
730
|
|
671
731
|
# Performs keys transformation and returns the altered
|
672
732
|
# <tt>ActionController::Parameters</tt> instance.
|
673
733
|
def transform_keys!(&block)
|
734
|
+
return to_enum(:transform_keys!) unless block_given?
|
674
735
|
@parameters.transform_keys!(&block)
|
675
736
|
self
|
676
737
|
end
|
677
738
|
|
739
|
+
# Returns a new <tt>ActionController::Parameters</tt> instance with the
|
740
|
+
# results of running +block+ once for every key. This includes the keys
|
741
|
+
# from the root hash and from all nested hashes and arrays. The values are unchanged.
|
742
|
+
def deep_transform_keys(&block)
|
743
|
+
new_instance_with_inherited_permitted_status(
|
744
|
+
@parameters.deep_transform_keys(&block)
|
745
|
+
)
|
746
|
+
end
|
747
|
+
|
748
|
+
# Returns the <tt>ActionController::Parameters</tt> instance changing its keys.
|
749
|
+
# This includes the keys from the root hash and from all nested hashes and arrays.
|
750
|
+
# The values are unchanged.
|
751
|
+
def deep_transform_keys!(&block)
|
752
|
+
@parameters.deep_transform_keys!(&block)
|
753
|
+
self
|
754
|
+
end
|
755
|
+
|
678
756
|
# Deletes a key-value pair from +Parameters+ and returns the value. If
|
679
757
|
# +key+ is not found, returns +nil+ (or, with optional code block, yields
|
680
758
|
# +key+ and returns the result). Cf. +#extract!+, which returns the
|
@@ -709,6 +787,28 @@ module ActionController
|
|
709
787
|
end
|
710
788
|
alias_method :delete_if, :reject!
|
711
789
|
|
790
|
+
# Returns a new instance of <tt>ActionController::Parameters</tt> with +nil+ values removed.
|
791
|
+
def compact
|
792
|
+
new_instance_with_inherited_permitted_status(@parameters.compact)
|
793
|
+
end
|
794
|
+
|
795
|
+
# Removes all +nil+ values in place and returns +self+, or +nil+ if no changes were made.
|
796
|
+
def compact!
|
797
|
+
self if @parameters.compact!
|
798
|
+
end
|
799
|
+
|
800
|
+
# Returns a new instance of <tt>ActionController::Parameters</tt> without the blank values.
|
801
|
+
# Uses Object#blank? for determining if a value is blank.
|
802
|
+
def compact_blank
|
803
|
+
reject { |_k, v| v.blank? }
|
804
|
+
end
|
805
|
+
|
806
|
+
# Removes all blank values in place and returns self.
|
807
|
+
# Uses Object#blank? for determining if a value is blank.
|
808
|
+
def compact_blank!
|
809
|
+
reject! { |_k, v| v.blank? }
|
810
|
+
end
|
811
|
+
|
712
812
|
# Returns values that were assigned to the given +keys+. Note that all the
|
713
813
|
# +Hash+ objects will be converted to <tt>ActionController::Parameters</tt>.
|
714
814
|
def values_at(*keys)
|
@@ -755,7 +855,7 @@ module ActionController
|
|
755
855
|
end
|
756
856
|
|
757
857
|
def inspect
|
758
|
-
"
|
858
|
+
"#<#{self.class} #{@parameters} permitted: #{@permitted}>"
|
759
859
|
end
|
760
860
|
|
761
861
|
def self.hook_into_yaml_loading # :nodoc:
|
@@ -780,7 +880,7 @@ module ActionController
|
|
780
880
|
@permitted = coder.map["ivars"][:@permitted]
|
781
881
|
when "!ruby/object:ActionController::Parameters"
|
782
882
|
# YAML's Object format. Only needed because of the format
|
783
|
-
#
|
883
|
+
# backwards compatibility above, otherwise equivalent to YAML's initialization.
|
784
884
|
@parameters, @permitted = coder.map["parameters"], coder.map["permitted"]
|
785
885
|
end
|
786
886
|
end
|
@@ -795,12 +895,16 @@ module ActionController
|
|
795
895
|
protected
|
796
896
|
attr_reader :parameters
|
797
897
|
|
798
|
-
|
799
|
-
|
898
|
+
attr_writer :permitted
|
899
|
+
|
900
|
+
def nested_attributes?
|
901
|
+
@parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
|
800
902
|
end
|
801
903
|
|
802
|
-
def
|
803
|
-
|
904
|
+
def each_nested_attribute
|
905
|
+
hash = self.class.new
|
906
|
+
self.each { |k, v| hash[k] = yield v if Parameters.nested_attribute?(k, v) }
|
907
|
+
hash
|
804
908
|
end
|
805
909
|
|
806
910
|
private
|
@@ -845,15 +949,13 @@ module ActionController
|
|
845
949
|
end
|
846
950
|
end
|
847
951
|
|
848
|
-
def each_element(object)
|
952
|
+
def each_element(object, &block)
|
849
953
|
case object
|
850
954
|
when Array
|
851
955
|
object.grep(Parameters).map { |el| yield el }.compact
|
852
956
|
when Parameters
|
853
|
-
if object.
|
854
|
-
|
855
|
-
object.each { |k, v| hash[k] = yield v }
|
856
|
-
hash
|
957
|
+
if object.nested_attributes?
|
958
|
+
object.each_nested_attribute(&block)
|
857
959
|
else
|
858
960
|
yield object
|
859
961
|
end
|
@@ -881,7 +983,7 @@ module ActionController
|
|
881
983
|
# --- Filtering ----------------------------------------------------------
|
882
984
|
#
|
883
985
|
|
884
|
-
# This is a
|
986
|
+
# This is a list of permitted scalar types that includes the ones
|
885
987
|
# supported in XML and JSON requests.
|
886
988
|
#
|
887
989
|
# This list is in particular used to filter ordinary requests, String goes
|
@@ -908,15 +1010,28 @@ module ActionController
|
|
908
1010
|
PERMITTED_SCALAR_TYPES.any? { |type| value.is_a?(type) }
|
909
1011
|
end
|
910
1012
|
|
911
|
-
|
912
|
-
|
913
|
-
|
1013
|
+
# Adds existing keys to the params if their values are scalar.
|
1014
|
+
#
|
1015
|
+
# For example:
|
1016
|
+
#
|
1017
|
+
# puts self.keys #=> ["zipcode(90210i)"]
|
1018
|
+
# params = {}
|
1019
|
+
#
|
1020
|
+
# permitted_scalar_filter(params, "zipcode")
|
1021
|
+
#
|
1022
|
+
# puts params.keys # => ["zipcode"]
|
1023
|
+
def permitted_scalar_filter(params, permitted_key)
|
1024
|
+
permitted_key = permitted_key.to_s
|
1025
|
+
|
1026
|
+
if has_key?(permitted_key) && permitted_scalar?(self[permitted_key])
|
1027
|
+
params[permitted_key] = self[permitted_key]
|
914
1028
|
end
|
915
1029
|
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
1030
|
+
each_key do |key|
|
1031
|
+
next unless key =~ /\(\d+[if]?\)\z/
|
1032
|
+
next unless $~.pre_match == permitted_key
|
1033
|
+
|
1034
|
+
params[key] = self[key] if permitted_scalar?(self[key])
|
920
1035
|
end
|
921
1036
|
end
|
922
1037
|
|
@@ -1001,8 +1116,8 @@ module ActionController
|
|
1001
1116
|
#
|
1002
1117
|
# It provides an interface for protecting attributes from end-user
|
1003
1118
|
# assignment. This makes Action Controller parameters forbidden
|
1004
|
-
# to be used in Active Model mass assignment until they have been
|
1005
|
-
#
|
1119
|
+
# to be used in Active Model mass assignment until they have been explicitly
|
1120
|
+
# enumerated.
|
1006
1121
|
#
|
1007
1122
|
# In addition, parameters can be marked as required and flow through a
|
1008
1123
|
# predefined raise/rescue flow to end up as a <tt>400 Bad Request</tt> with no
|
@@ -1038,7 +1153,7 @@ module ActionController
|
|
1038
1153
|
# end
|
1039
1154
|
#
|
1040
1155
|
# In order to use <tt>accepts_nested_attributes_for</tt> with Strong \Parameters, you
|
1041
|
-
# will need to specify which nested attributes should be
|
1156
|
+
# will need to specify which nested attributes should be permitted. You might want
|
1042
1157
|
# to allow +:id+ and +:_destroy+, see ActiveRecord::NestedAttributes for more information.
|
1043
1158
|
#
|
1044
1159
|
# class Person
|
@@ -1056,7 +1171,7 @@ module ActionController
|
|
1056
1171
|
# private
|
1057
1172
|
#
|
1058
1173
|
# def person_params
|
1059
|
-
# # It's mandatory to specify the nested attributes that should be
|
1174
|
+
# # It's mandatory to specify the nested attributes that should be permitted.
|
1060
1175
|
# # If you use `permit` with just the key that points to the nested attributes hash,
|
1061
1176
|
# # it will return an empty hash.
|
1062
1177
|
# params.require(:person).permit(:name, :age, pets_attributes: [ :id, :name, :category ])
|
@@ -1066,9 +1181,6 @@ module ActionController
|
|
1066
1181
|
# See ActionController::Parameters.require and ActionController::Parameters.permit
|
1067
1182
|
# for more information.
|
1068
1183
|
module StrongParameters
|
1069
|
-
extend ActiveSupport::Concern
|
1070
|
-
include ActiveSupport::Rescuable
|
1071
|
-
|
1072
1184
|
# Returns a new ActionController::Parameters object that
|
1073
1185
|
# has been instantiated with the <tt>request.parameters</tt>.
|
1074
1186
|
def params
|
@@ -44,7 +44,7 @@ module ActionController
|
|
44
44
|
options[:original_script_name] = original_script_name
|
45
45
|
else
|
46
46
|
if same_origin
|
47
|
-
options[:script_name] = request.script_name.empty? ? ""
|
47
|
+
options[:script_name] = request.script_name.empty? ? "" : request.script_name.dup
|
48
48
|
else
|
49
49
|
options[:script_name] = script_name
|
50
50
|
end
|
@@ -26,16 +26,15 @@ module ActionController
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def build(action, app =
|
29
|
+
def build(action, app = nil, &block)
|
30
30
|
action = action.to_s
|
31
31
|
|
32
|
-
middlewares.reverse.inject(app) do |a, middleware|
|
32
|
+
middlewares.reverse.inject(app || block) do |a, middleware|
|
33
33
|
middleware.valid?(action) ? middleware.build(a) : a
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
|
-
|
39
38
|
INCLUDE = ->(list, action) { list.include? action }
|
40
39
|
EXCLUDE = ->(list, action) { !list.include? action }
|
41
40
|
NULL = ->(list, action) { true }
|
@@ -127,7 +126,7 @@ module ActionController
|
|
127
126
|
# ==== Returns
|
128
127
|
# * <tt>string</tt>
|
129
128
|
def self.controller_name
|
130
|
-
@controller_name ||= name.demodulize.
|
129
|
+
@controller_name ||= (name.demodulize.delete_suffix("Controller").underscore unless anonymous?)
|
131
130
|
end
|
132
131
|
|
133
132
|
def self.make_response!(request)
|
@@ -136,7 +135,7 @@ module ActionController
|
|
136
135
|
end
|
137
136
|
end
|
138
137
|
|
139
|
-
def self.
|
138
|
+
def self.action_encoding_template(action) # :nodoc:
|
140
139
|
false
|
141
140
|
end
|
142
141
|
|
@@ -148,7 +147,7 @@ module ActionController
|
|
148
147
|
attr_internal :response, :request
|
149
148
|
delegate :session, to: "@_request"
|
150
149
|
delegate :headers, :status=, :location=, :content_type=,
|
151
|
-
:status, :location, :content_type, to: "@_response"
|
150
|
+
:status, :location, :content_type, :media_type, to: "@_response"
|
152
151
|
|
153
152
|
def initialize
|
154
153
|
@_request = nil
|
@@ -217,10 +216,13 @@ module ActionController
|
|
217
216
|
super
|
218
217
|
end
|
219
218
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
219
|
+
class << self
|
220
|
+
# Pushes the given Rack middleware and its arguments to the bottom of the
|
221
|
+
# middleware stack.
|
222
|
+
def use(*args, &block)
|
223
|
+
middleware_stack.use(*args, &block)
|
224
|
+
end
|
225
|
+
ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
|
224
226
|
end
|
225
227
|
|
226
228
|
# Alias for +middleware_stack+.
|
@@ -7,7 +7,7 @@ module ActionController
|
|
7
7
|
super
|
8
8
|
return unless klass.respond_to?(:helpers_path=)
|
9
9
|
|
10
|
-
if namespace = klass.
|
10
|
+
if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_helpers_paths) }
|
11
11
|
paths = namespace.railtie_helpers_paths
|
12
12
|
else
|
13
13
|
paths = ActionController::Helpers.helpers_path
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/hash/keys"
|
4
|
-
|
5
3
|
module ActionController
|
6
4
|
# ActionController::Renderer allows you to render arbitrary templates
|
7
5
|
# without requirement of being in controller actions.
|
@@ -67,10 +65,29 @@ module ActionController
|
|
67
65
|
def initialize(controller, env, defaults)
|
68
66
|
@controller = controller
|
69
67
|
@defaults = defaults
|
70
|
-
@env = normalize_keys defaults
|
68
|
+
@env = normalize_keys defaults, env
|
71
69
|
end
|
72
70
|
|
73
71
|
# Render templates with any options from ActionController::Base#render_to_string.
|
72
|
+
#
|
73
|
+
# The primary options are:
|
74
|
+
# * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
|
75
|
+
# * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
|
76
|
+
# It shouldn’t be used directly with unsanitized user input due to lack of validation.
|
77
|
+
# * <tt>:inline</tt> - Renders an ERB template string.
|
78
|
+
# * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>.
|
79
|
+
# * <tt>:html</tt> - Renders the provided HTML safe string, otherwise
|
80
|
+
# performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>.
|
81
|
+
# * <tt>:json</tt> - Renders the provided hash or object in JSON. You don't
|
82
|
+
# need to call <tt>.to_json</tt> on the object you want to render.
|
83
|
+
# * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>.
|
84
|
+
#
|
85
|
+
# If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, then:
|
86
|
+
#
|
87
|
+
# If an object responding to +render_in+ is passed, +render_in+ is called on the object,
|
88
|
+
# passing in the current view context.
|
89
|
+
#
|
90
|
+
# Otherwise, a partial is rendered using the second parameter as the locals hash.
|
74
91
|
def render(*args)
|
75
92
|
raise "missing controller" unless controller
|
76
93
|
|
@@ -82,11 +99,18 @@ module ActionController
|
|
82
99
|
instance.set_response! controller.make_response!(request)
|
83
100
|
instance.render_to_string(*args)
|
84
101
|
end
|
102
|
+
alias_method :render_to_string, :render # :nodoc:
|
85
103
|
|
86
104
|
private
|
87
|
-
def normalize_keys(env)
|
105
|
+
def normalize_keys(defaults, env)
|
88
106
|
new_env = {}
|
89
107
|
env.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
|
108
|
+
|
109
|
+
defaults.each_pair do |k, v|
|
110
|
+
key = rack_key_for(k)
|
111
|
+
new_env[key] = rack_value_for(k, v) unless new_env.key?(key)
|
112
|
+
end
|
113
|
+
|
90
114
|
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
|
91
115
|
new_env
|
92
116
|
end
|
@@ -99,19 +123,19 @@ module ActionController
|
|
99
123
|
input: "rack.input"
|
100
124
|
}
|
101
125
|
|
102
|
-
IDENTITY = ->(_) { _ }
|
103
|
-
|
104
|
-
RACK_VALUE_TRANSLATION = {
|
105
|
-
https: ->(v) { v ? "on" : "off" },
|
106
|
-
method: ->(v) { v.upcase },
|
107
|
-
}
|
108
|
-
|
109
126
|
def rack_key_for(key)
|
110
|
-
RACK_KEY_TRANSLATION
|
127
|
+
RACK_KEY_TRANSLATION[key] || key.to_s
|
111
128
|
end
|
112
129
|
|
113
130
|
def rack_value_for(key, value)
|
114
|
-
|
131
|
+
case key
|
132
|
+
when :https
|
133
|
+
value ? "on" : "off"
|
134
|
+
when :method
|
135
|
+
-value.upcase
|
136
|
+
else
|
137
|
+
value
|
138
|
+
end
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
-
module TemplateAssertions
|
4
|
+
module TemplateAssertions # :nodoc:
|
5
5
|
def assert_template(options = {}, message = nil)
|
6
6
|
raise NoMethodError,
|
7
7
|
"assert_template has been extracted to a gem. To continue using it,
|