actionpack 6.1.7.3 → 7.0.8

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.

Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +320 -390
  3. data/MIT-LICENSE +1 -0
  4. data/README.rdoc +4 -5
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +13 -26
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +21 -7
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +17 -12
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/rendering.rb +9 -11
  16. data/lib/abstract_controller/translation.rb +5 -4
  17. data/lib/abstract_controller/url_for.rb +4 -6
  18. data/lib/action_controller/api.rb +7 -7
  19. data/lib/action_controller/base.rb +5 -4
  20. data/lib/action_controller/form_builder.rb +2 -2
  21. data/lib/action_controller/log_subscriber.rb +4 -3
  22. data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
  23. data/lib/action_controller/metal/conditional_get.rb +137 -102
  24. data/lib/action_controller/metal/content_security_policy.rb +36 -2
  25. data/lib/action_controller/metal/cookies.rb +1 -1
  26. data/lib/action_controller/metal/data_streaming.rb +23 -31
  27. data/lib/action_controller/metal/etag_with_flash.rb +1 -1
  28. data/lib/action_controller/metal/exceptions.rb +19 -30
  29. data/lib/action_controller/metal/flash.rb +6 -2
  30. data/lib/action_controller/metal/head.rb +1 -1
  31. data/lib/action_controller/metal/helpers.rb +2 -2
  32. data/lib/action_controller/metal/http_authentication.rb +66 -39
  33. data/lib/action_controller/metal/instrumentation.rb +57 -52
  34. data/lib/action_controller/metal/live.rb +43 -2
  35. data/lib/action_controller/metal/mime_responds.rb +3 -3
  36. data/lib/action_controller/metal/params_wrapper.rb +20 -11
  37. data/lib/action_controller/metal/permissions_policy.rb +19 -28
  38. data/lib/action_controller/metal/redirecting.rb +111 -19
  39. data/lib/action_controller/metal/renderers.rb +12 -13
  40. data/lib/action_controller/metal/rendering.rb +121 -9
  41. data/lib/action_controller/metal/request_forgery_protection.rb +83 -32
  42. data/lib/action_controller/metal/rescue.rb +5 -4
  43. data/lib/action_controller/metal/streaming.rb +7 -9
  44. data/lib/action_controller/metal/strong_parameters.rb +138 -115
  45. data/lib/action_controller/metal/testing.rb +9 -2
  46. data/lib/action_controller/metal/url_for.rb +3 -5
  47. data/lib/action_controller/metal.rb +10 -13
  48. data/lib/action_controller/railtie.rb +50 -6
  49. data/lib/action_controller/renderer.rb +1 -20
  50. data/lib/action_controller/test_case.rb +28 -7
  51. data/lib/action_controller.rb +2 -5
  52. data/lib/action_dispatch/http/cache.rb +20 -13
  53. data/lib/action_dispatch/http/content_security_policy.rb +113 -36
  54. data/lib/action_dispatch/http/filter_parameters.rb +4 -19
  55. data/lib/action_dispatch/http/headers.rb +1 -1
  56. data/lib/action_dispatch/http/mime_negotiation.rb +15 -5
  57. data/lib/action_dispatch/http/mime_type.rb +9 -11
  58. data/lib/action_dispatch/http/parameters.rb +5 -5
  59. data/lib/action_dispatch/http/permissions_policy.rb +17 -1
  60. data/lib/action_dispatch/http/request.rb +27 -37
  61. data/lib/action_dispatch/http/response.rb +3 -20
  62. data/lib/action_dispatch/http/upload.rb +13 -2
  63. data/lib/action_dispatch/http/url.rb +11 -19
  64. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  65. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  66. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  67. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  68. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  69. data/lib/action_dispatch/journey/route.rb +6 -13
  70. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  71. data/lib/action_dispatch/journey/router.rb +1 -1
  72. data/lib/action_dispatch/journey/routes.rb +3 -3
  73. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  74. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  75. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  76. data/lib/action_dispatch/middleware/cookies.rb +20 -13
  77. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  78. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  79. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  80. data/lib/action_dispatch/middleware/executor.rb +3 -0
  81. data/lib/action_dispatch/middleware/flash.rb +17 -18
  82. data/lib/action_dispatch/middleware/host_authorization.rb +13 -17
  83. data/lib/action_dispatch/middleware/remote_ip.rb +20 -8
  84. data/lib/action_dispatch/middleware/request_id.rb +3 -3
  85. data/lib/action_dispatch/middleware/server_timing.rb +76 -0
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  87. data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
  88. data/lib/action_dispatch/middleware/show_exceptions.rb +17 -16
  89. data/lib/action_dispatch/middleware/stack.rb +27 -9
  90. data/lib/action_dispatch/middleware/static.rb +5 -9
  91. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  92. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  93. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  94. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
  95. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
  96. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  97. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  98. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  99. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  101. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  102. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  103. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  104. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +22 -22
  105. data/lib/action_dispatch/railtie.rb +8 -2
  106. data/lib/action_dispatch/request/session.rb +43 -13
  107. data/lib/action_dispatch/routing/inspector.rb +1 -1
  108. data/lib/action_dispatch/routing/mapper.rb +82 -83
  109. data/lib/action_dispatch/routing/redirection.rb +5 -2
  110. data/lib/action_dispatch/routing/route_set.rb +17 -7
  111. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  112. data/lib/action_dispatch/routing/url_for.rb +24 -25
  113. data/lib/action_dispatch/routing.rb +5 -6
  114. data/lib/action_dispatch/system_test_case.rb +5 -5
  115. data/lib/action_dispatch/system_testing/browser.rb +3 -13
  116. data/lib/action_dispatch/system_testing/driver.rb +34 -10
  117. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +11 -7
  118. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
  119. data/lib/action_dispatch/testing/assertions/response.rb +1 -1
  120. data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
  121. data/lib/action_dispatch/testing/assertions.rb +2 -5
  122. data/lib/action_dispatch/testing/integration.rb +6 -8
  123. data/lib/action_dispatch/testing/test_process.rb +3 -29
  124. data/lib/action_dispatch/testing/test_response.rb +20 -2
  125. data/lib/action_dispatch.rb +1 -0
  126. data/lib/action_pack/gem_version.rb +5 -5
  127. data/lib/action_pack/version.rb +1 -1
  128. metadata +16 -15
@@ -27,28 +27,13 @@ module ActionController
27
27
  super("param is missing or the value is empty: #{param}")
28
28
  end
29
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
30
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
31
+ include DidYouMean::Correctable # :nodoc:
38
32
 
39
- maybe_these.sort_by { |n|
40
- DidYouMean::Jaro.distance(@error.param.to_s, n)
41
- }.reverse.first(4)
42
- else
43
- []
44
- end
33
+ def corrections # :nodoc:
34
+ @corrections ||= DidYouMean::SpellChecker.new(dictionary: keys).correct(param.to_s)
45
35
  end
46
36
  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
52
37
  end
53
38
 
54
39
  # Raised when a supplied parameter is not expected and
@@ -96,7 +81,7 @@ module ActionController
96
81
  # })
97
82
  #
98
83
  # permitted = params.require(:person).permit(:name, :age)
99
- # permitted # => <ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>
84
+ # permitted # => #<ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>
100
85
  # permitted.permitted? # => true
101
86
  #
102
87
  # Person.first.update!(permitted)
@@ -106,11 +91,13 @@ module ActionController
106
91
  #
107
92
  # * +permit_all_parameters+ - If it's +true+, all the parameters will be
108
93
  # permitted by default. The default is +false+.
109
- # * +action_on_unpermitted_parameters+ - Allow to control the behavior when parameters
110
- # that are not explicitly permitted are found. The values can be +false+ to just filter them
111
- # out, <tt>:log</tt> to additionally write a message on the logger, or <tt>:raise</tt> to raise
112
- # ActionController::UnpermittedParameters exception. The default value is <tt>:log</tt>
113
- # in test and development environments, +false+ otherwise.
94
+ # * +action_on_unpermitted_parameters+ - Controls behavior when parameters that are not explicitly
95
+ # permitted are found. The default value is <tt>:log</tt> in test and development environments,
96
+ # +false+ otherwise. The values can be:
97
+ # * +false+ to take no action.
98
+ # * <tt>:log</tt> to emit an <tt>ActiveSupport::Notifications.instrument</tt> event on the
99
+ # <tt>unpermitted_parameters.action_controller</tt> topic and log at the DEBUG level.
100
+ # * <tt>:raise</tt> to raise an ActionController::UnpermittedParameters exception.
114
101
  #
115
102
  # Examples:
116
103
  #
@@ -124,7 +111,7 @@ module ActionController
124
111
  #
125
112
  # params = ActionController::Parameters.new(a: "123", b: "456")
126
113
  # params.permit(:c)
127
- # # => <ActionController::Parameters {} permitted: true>
114
+ # # => #<ActionController::Parameters {} permitted: true>
128
115
  #
129
116
  # ActionController::Parameters.action_on_unpermitted_parameters = :raise
130
117
  #
@@ -159,7 +146,7 @@ module ActionController
159
146
  # :method: each_key
160
147
  #
161
148
  # :call-seq:
162
- # each_key()
149
+ # each_key(&block)
163
150
  #
164
151
  # Calls block once for each key in the parameters, passing the key.
165
152
  # If no block is given, an enumerator is returned instead.
@@ -172,14 +159,6 @@ module ActionController
172
159
  #
173
160
  # Returns true if the parameters have no key/value pairs.
174
161
 
175
- ##
176
- # :method: has_key?
177
- #
178
- # :call-seq:
179
- # has_key?(key)
180
- #
181
- # Returns true if the given key is present in the parameters.
182
-
183
162
  ##
184
163
  # :method: has_value?
185
164
  #
@@ -196,22 +175,6 @@ module ActionController
196
175
  #
197
176
  # Returns true if the given key is present in the parameters.
198
177
 
199
- ##
200
- # :method: key?
201
- #
202
- # :call-seq:
203
- # key?(key)
204
- #
205
- # Returns true if the given key is present in the parameters.
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
-
215
178
  ##
216
179
  # :method: keys
217
180
  #
@@ -243,13 +206,17 @@ module ActionController
243
206
  # values()
244
207
  #
245
208
  # Returns a new array of the values of the parameters.
246
- delegate :keys, :key?, :has_key?, :member?, :values, :has_value?, :value?, :empty?, :include?,
209
+ delegate :keys, :values, :has_value?, :value?, :empty?, :include?,
247
210
  :as_json, :to_s, :each_key, to: :@parameters
248
211
 
212
+ alias_method :has_key?, :include?
213
+ alias_method :key?, :include?
214
+ alias_method :member?, :include?
215
+
249
216
  # By default, never raise an UnpermittedParameters exception if these
250
217
  # params are present. The default includes both 'controller' and 'action'
251
218
  # because they are added by Rails and should be of no concern. One way
252
- # to change these is to specify `always_permitted_parameters` in your
219
+ # to change these is to specify +always_permitted_parameters+ in your
253
220
  # config. For instance:
254
221
  #
255
222
  # config.action_controller.always_permitted_parameters = %w( controller action format )
@@ -261,7 +228,7 @@ module ActionController
261
228
  end
262
229
  end
263
230
 
264
- # Returns a new instance of <tt>ActionController::Parameters</tt>.
231
+ # Returns a new <tt>ActionController::Parameters</tt> instance.
265
232
  # Also, sets the +permitted+ attribute to the default value of
266
233
  # <tt>ActionController::Parameters.permit_all_parameters</tt>.
267
234
  #
@@ -277,8 +244,9 @@ module ActionController
277
244
  # params = ActionController::Parameters.new(name: "Francesco")
278
245
  # params.permitted? # => true
279
246
  # Person.new(params) # => #<Person id: nil, name: "Francesco">
280
- def initialize(parameters = {})
247
+ def initialize(parameters = {}, logging_context = {})
281
248
  @parameters = parameters.with_indifferent_access
249
+ @logging_context = logging_context
282
250
  @permitted = self.class.permit_all_parameters
283
251
  end
284
252
 
@@ -291,13 +259,18 @@ module ActionController
291
259
  @parameters == other
292
260
  end
293
261
  end
294
- alias eql? ==
262
+
263
+ def eql?(other)
264
+ self.class == other.class &&
265
+ permitted? == other.permitted? &&
266
+ parameters.eql?(other.parameters)
267
+ end
295
268
 
296
269
  def hash
297
- [@parameters.hash, @permitted].hash
270
+ [self.class, @parameters, @permitted].hash
298
271
  end
299
272
 
300
- # Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
273
+ # Returns a safe ActiveSupport::HashWithIndifferentAccess
301
274
  # representation of the parameters with all unpermitted keys removed.
302
275
  #
303
276
  # params = ActionController::Parameters.new({
@@ -357,18 +330,15 @@ module ActionController
357
330
  # safe_params.to_query("user")
358
331
  # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
359
332
  #
360
- # The string pairs "key=value" that conform the query string
333
+ # The string pairs <tt>"key=value"</tt> that conform the query string
361
334
  # are sorted lexicographically in ascending order.
362
- #
363
- # This method is also aliased as +to_param+.
364
335
  def to_query(*args)
365
336
  to_h.to_query(*args)
366
337
  end
367
338
  alias_method :to_param, :to_query
368
339
 
369
- # Returns an unsafe, unfiltered
370
- # <tt>ActiveSupport::HashWithIndifferentAccess</tt> representation of the
371
- # parameters.
340
+ # Returns an unsafe, unfiltered ActiveSupport::HashWithIndifferentAccess
341
+ # representation of the parameters.
372
342
  #
373
343
  # params = ActionController::Parameters.new({
374
344
  # name: "Senjougahara Hitagi",
@@ -408,7 +378,7 @@ module ActionController
408
378
  # looping in the common use case permit + mass-assignment. Defined in a
409
379
  # method to instantiate it only if needed.
410
380
  #
411
- # Testing membership still loops, but it's going to be faster than our own
381
+ # \Testing membership still loops, but it's going to be faster than our own
412
382
  # loop that converts values. Also, we are not going to build a new array
413
383
  # object per fetch.
414
384
  def converted_arrays
@@ -454,9 +424,9 @@ module ActionController
454
424
  # either present or the singleton +false+, returns said value:
455
425
  #
456
426
  # ActionController::Parameters.new(person: { name: "Francesco" }).require(:person)
457
- # # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
427
+ # # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
458
428
  #
459
- # Otherwise raises <tt>ActionController::ParameterMissing</tt>:
429
+ # Otherwise raises ActionController::ParameterMissing:
460
430
  #
461
431
  # ActionController::Parameters.new.require(:person)
462
432
  # # ActionController::ParameterMissing: param is missing or the value is empty: person
@@ -508,7 +478,6 @@ module ActionController
508
478
  end
509
479
  end
510
480
 
511
- # Alias of #require.
512
481
  alias :required :require
513
482
 
514
483
  # Returns a new <tt>ActionController::Parameters</tt> instance that
@@ -530,7 +499,7 @@ module ActionController
530
499
  # +:name+ passes if it is a key of +params+ whose associated value is of type
531
500
  # +String+, +Symbol+, +NilClass+, +Numeric+, +TrueClass+, +FalseClass+,
532
501
  # +Date+, +Time+, +DateTime+, +StringIO+, +IO+,
533
- # +ActionDispatch::Http::UploadedFile+ or +Rack::Test::UploadedFile+.
502
+ # ActionDispatch::Http::UploadedFile or +Rack::Test::UploadedFile+.
534
503
  # Otherwise, the key +:name+ is filtered out.
535
504
  #
536
505
  # You may declare that the parameter should be an array of permitted scalars
@@ -582,13 +551,48 @@ module ActionController
582
551
  # })
583
552
  #
584
553
  # params.require(:person).permit(:contact)
585
- # # => <ActionController::Parameters {} permitted: true>
554
+ # # => #<ActionController::Parameters {} permitted: true>
586
555
  #
587
556
  # params.require(:person).permit(contact: :phone)
588
- # # => <ActionController::Parameters {"contact"=><ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>
557
+ # # => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>
589
558
  #
590
559
  # params.require(:person).permit(contact: [ :email, :phone ])
591
- # # => <ActionController::Parameters {"contact"=><ActionController::Parameters {"email"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>
560
+ # # => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"email"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>
561
+ #
562
+ # If your parameters specify multiple parameters indexed by a number,
563
+ # you can permit each set of parameters under the numeric key to be the same using the same syntax as permitting a single item.
564
+ #
565
+ # params = ActionController::Parameters.new({
566
+ # person: {
567
+ # '0': {
568
+ # email: "none@test.com",
569
+ # phone: "555-1234"
570
+ # },
571
+ # '1': {
572
+ # email: "nothing@test.com",
573
+ # phone: "555-6789"
574
+ # },
575
+ # }
576
+ # })
577
+ # params.permit(person: [:email]).to_h
578
+ # # => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"email"=>"nothing@test.com"}}}
579
+ #
580
+ # If you want to specify what keys you want from each numeric key, you can instead specify each one individually
581
+ #
582
+ # params = ActionController::Parameters.new({
583
+ # person: {
584
+ # '0': {
585
+ # email: "none@test.com",
586
+ # phone: "555-1234"
587
+ # },
588
+ # '1': {
589
+ # email: "nothing@test.com",
590
+ # phone: "555-6789"
591
+ # },
592
+ # }
593
+ # })
594
+ # params.permit(person: { '0': [:email], '1': [:phone]}).to_h
595
+ # # => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"phone"=>"555-6789"}}}
592
596
  def permit(*filters)
593
597
  params = self.class.new
594
598
 
@@ -610,29 +614,29 @@ module ActionController
610
614
  # returns +nil+.
611
615
  #
612
616
  # params = ActionController::Parameters.new(person: { name: "Francesco" })
613
- # params[:person] # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
617
+ # params[:person] # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
614
618
  # params[:none] # => nil
615
619
  def [](key)
616
620
  convert_hashes_to_parameters(key, @parameters[key])
617
621
  end
618
622
 
619
623
  # Assigns a value to a given +key+. The given key may still get filtered out
620
- # when +permit+ is called.
624
+ # when #permit is called.
621
625
  def []=(key, value)
622
626
  @parameters[key] = value
623
627
  end
624
628
 
625
629
  # Returns a parameter for the given +key+. If the +key+
626
630
  # can't be found, there are several options: With no other arguments,
627
- # it will raise an <tt>ActionController::ParameterMissing</tt> error;
631
+ # it will raise an ActionController::ParameterMissing error;
628
632
  # if a second argument is given, then that is returned (converted to an
629
- # instance of ActionController::Parameters if possible); if a block
633
+ # instance of +ActionController::Parameters+ if possible); if a block
630
634
  # is given, then that will be run and its result returned.
631
635
  #
632
636
  # params = ActionController::Parameters.new(person: { name: "Francesco" })
633
- # params.fetch(:person) # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
637
+ # params.fetch(:person) # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
634
638
  # params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none
635
- # params.fetch(:none, {}) # => <ActionController::Parameters {} permitted: false>
639
+ # params.fetch(:none, {}) # => #<ActionController::Parameters {} permitted: false>
636
640
  # params.fetch(:none, "Francesco") # => "Francesco"
637
641
  # params.fetch(:none) { "Francesco" } # => "Francesco"
638
642
  def fetch(key, *args)
@@ -666,13 +670,13 @@ module ActionController
666
670
  # don't exist, returns an empty hash.
667
671
  #
668
672
  # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
669
- # params.slice(:a, :b) # => <ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
670
- # params.slice(:d) # => <ActionController::Parameters {} permitted: false>
673
+ # params.slice(:a, :b) # => #<ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
674
+ # params.slice(:d) # => #<ActionController::Parameters {} permitted: false>
671
675
  def slice(*keys)
672
676
  new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
673
677
  end
674
678
 
675
- # Returns current <tt>ActionController::Parameters</tt> instance which
679
+ # Returns the current <tt>ActionController::Parameters</tt> instance which
676
680
  # contains only the given +keys+.
677
681
  def slice!(*keys)
678
682
  @parameters.slice!(*keys)
@@ -683,8 +687,8 @@ module ActionController
683
687
  # filters out the given +keys+.
684
688
  #
685
689
  # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
686
- # params.except(:a, :b) # => <ActionController::Parameters {"c"=>3} permitted: false>
687
- # params.except(:d) # => <ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
690
+ # params.except(:a, :b) # => #<ActionController::Parameters {"c"=>3} permitted: false>
691
+ # params.except(:d) # => #<ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
688
692
  def except(*keys)
689
693
  new_instance_with_inherited_permitted_status(@parameters.except(*keys))
690
694
  end
@@ -692,18 +696,18 @@ module ActionController
692
696
  # Removes and returns the key/value pairs matching the given keys.
693
697
  #
694
698
  # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
695
- # params.extract!(:a, :b) # => <ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
696
- # params # => <ActionController::Parameters {"c"=>3} permitted: false>
699
+ # params.extract!(:a, :b) # => #<ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
700
+ # params # => #<ActionController::Parameters {"c"=>3} permitted: false>
697
701
  def extract!(*keys)
698
702
  new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
699
703
  end
700
704
 
701
- # Returns a new <tt>ActionController::Parameters</tt> with the results of
705
+ # Returns a new <tt>ActionController::Parameters</tt> instance with the results of
702
706
  # running +block+ once for every value. The keys are unchanged.
703
707
  #
704
708
  # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
705
709
  # params.transform_values { |x| x * 2 }
706
- # # => <ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
710
+ # # => #<ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
707
711
  def transform_values
708
712
  return to_enum(:transform_values) unless block_given?
709
713
  new_instance_with_inherited_permitted_status(
@@ -745,9 +749,9 @@ module ActionController
745
749
  )
746
750
  end
747
751
 
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.
752
+ # Returns the same <tt>ActionController::Parameters</tt> instance with
753
+ # changed keys. This includes the keys from the root hash and from all
754
+ # nested hashes and arrays. The values are unchanged.
751
755
  def deep_transform_keys!(&block)
752
756
  @parameters.deep_transform_keys!(&block)
753
757
  self
@@ -755,13 +759,13 @@ module ActionController
755
759
 
756
760
  # Deletes a key-value pair from +Parameters+ and returns the value. If
757
761
  # +key+ is not found, returns +nil+ (or, with optional code block, yields
758
- # +key+ and returns the result). Cf. +#extract!+, which returns the
759
- # corresponding +ActionController::Parameters+ object.
762
+ # +key+ and returns the result). This method is similar to #extract!, which
763
+ # returns the corresponding +ActionController::Parameters+ object.
760
764
  def delete(key, &block)
761
765
  convert_value_to_parameters(@parameters.delete(key, &block))
762
766
  end
763
767
 
764
- # Returns a new instance of <tt>ActionController::Parameters</tt> with only
768
+ # Returns a new <tt>ActionController::Parameters</tt> instance with only
765
769
  # items that the block evaluates to true.
766
770
  def select(&block)
767
771
  new_instance_with_inherited_permitted_status(@parameters.select(&block))
@@ -774,7 +778,7 @@ module ActionController
774
778
  end
775
779
  alias_method :keep_if, :select!
776
780
 
777
- # Returns a new instance of <tt>ActionController::Parameters</tt> with items
781
+ # Returns a new <tt>ActionController::Parameters</tt> instance with items
778
782
  # that the block evaluates to true removed.
779
783
  def reject(&block)
780
784
  new_instance_with_inherited_permitted_status(@parameters.reject(&block))
@@ -787,7 +791,7 @@ module ActionController
787
791
  end
788
792
  alias_method :delete_if, :reject!
789
793
 
790
- # Returns a new instance of <tt>ActionController::Parameters</tt> with +nil+ values removed.
794
+ # Returns a new <tt>ActionController::Parameters</tt> instance with +nil+ values removed.
791
795
  def compact
792
796
  new_instance_with_inherited_permitted_status(@parameters.compact)
793
797
  end
@@ -797,7 +801,7 @@ module ActionController
797
801
  self if @parameters.compact!
798
802
  end
799
803
 
800
- # Returns a new instance of <tt>ActionController::Parameters</tt> without the blank values.
804
+ # Returns a new <tt>ActionController::Parameters</tt> instance without the blank values.
801
805
  # Uses Object#blank? for determining if a value is blank.
802
806
  def compact_blank
803
807
  reject { |_k, v| v.blank? }
@@ -815,7 +819,7 @@ module ActionController
815
819
  convert_value_to_parameters(@parameters.values_at(*keys))
816
820
  end
817
821
 
818
- # Returns a new <tt>ActionController::Parameters</tt> with all keys from
822
+ # Returns a new <tt>ActionController::Parameters</tt> instance with all keys from
819
823
  # +other_hash+ merged into current hash.
820
824
  def merge(other_hash)
821
825
  new_instance_with_inherited_permitted_status(
@@ -823,15 +827,15 @@ module ActionController
823
827
  )
824
828
  end
825
829
 
826
- # Returns current <tt>ActionController::Parameters</tt> instance with
830
+ # Returns the current <tt>ActionController::Parameters</tt> instance with
827
831
  # +other_hash+ merged into current hash.
828
832
  def merge!(other_hash)
829
833
  @parameters.merge!(other_hash.to_h)
830
834
  self
831
835
  end
832
836
 
833
- # Returns a new <tt>ActionController::Parameters</tt> with all keys from
834
- # current hash merged into +other_hash+.
837
+ # Returns a new <tt>ActionController::Parameters</tt> instance with all keys
838
+ # from current hash merged into +other_hash+.
835
839
  def reverse_merge(other_hash)
836
840
  new_instance_with_inherited_permitted_status(
837
841
  other_hash.to_h.merge(@parameters)
@@ -839,7 +843,7 @@ module ActionController
839
843
  end
840
844
  alias_method :with_defaults, :reverse_merge
841
845
 
842
- # Returns current <tt>ActionController::Parameters</tt> instance with
846
+ # Returns the current <tt>ActionController::Parameters</tt> instance with
843
847
  # current hash merged into +other_hash+.
844
848
  def reverse_merge!(other_hash)
845
849
  @parameters.merge!(other_hash.to_h) { |key, left, right| left }
@@ -885,9 +889,13 @@ module ActionController
885
889
  end
886
890
  end
887
891
 
888
- # Returns duplicate of object including all parameters.
892
+ def encode_with(coder) # :nodoc:
893
+ coder.map = { "parameters" => @parameters, "permitted" => @permitted }
894
+ end
895
+
896
+ # Returns a duplicate +ActionController::Parameters+ instance with the same permitted parameters.
889
897
  def deep_dup
890
- self.class.new(@parameters.deep_dup).tap do |duplicate|
898
+ self.class.new(@parameters.deep_dup, @logging_context).tap do |duplicate|
891
899
  duplicate.permitted = @permitted
892
900
  end
893
901
  end
@@ -909,7 +917,7 @@ module ActionController
909
917
 
910
918
  private
911
919
  def new_instance_with_inherited_permitted_status(hash)
912
- self.class.new(hash).tap do |new_instance|
920
+ self.class.new(hash, @logging_context).tap do |new_instance|
913
921
  new_instance.permitted = @permitted
914
922
  end
915
923
  end
@@ -943,18 +951,24 @@ module ActionController
943
951
  converted_arrays << converted.dup
944
952
  converted
945
953
  when Hash
946
- self.class.new(value)
954
+ self.class.new(value, @logging_context)
947
955
  else
948
956
  value
949
957
  end
950
958
  end
951
959
 
952
- def each_element(object, &block)
960
+ def specify_numeric_keys?(filter)
961
+ if filter.respond_to?(:keys)
962
+ filter.keys.any? { |key| /\A-?\d+\z/.match?(key) }
963
+ end
964
+ end
965
+
966
+ def each_element(object, filter, &block)
953
967
  case object
954
968
  when Array
955
- object.grep(Parameters).map { |el| yield el }.compact
969
+ object.grep(Parameters).filter_map(&block)
956
970
  when Parameters
957
- if object.nested_attributes?
971
+ if object.nested_attributes? && !specify_numeric_keys?(filter)
958
972
  object.each_nested_attribute(&block)
959
973
  else
960
974
  yield object
@@ -968,7 +982,7 @@ module ActionController
968
982
  case self.class.action_on_unpermitted_parameters
969
983
  when :log
970
984
  name = "unpermitted_parameters.action_controller"
971
- ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys)
985
+ ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys, context: @logging_context)
972
986
  when :raise
973
987
  raise ActionController::UnpermittedParameters.new(unpermitted_keys)
974
988
  end
@@ -986,10 +1000,11 @@ module ActionController
986
1000
  # This is a list of permitted scalar types that includes the ones
987
1001
  # supported in XML and JSON requests.
988
1002
  #
989
- # This list is in particular used to filter ordinary requests, String goes
1003
+ # This list is in particular used to filter ordinary requests, \String goes
990
1004
  # as first element to quickly short-circuit the common case.
991
1005
  #
992
- # If you modify this collection please update the API of +permit+ above.
1006
+ # If you modify this collection please update the one in the #permit doc
1007
+ # as well.
993
1008
  PERMITTED_SCALAR_TYPES = [
994
1009
  String,
995
1010
  Symbol,
@@ -1045,8 +1060,8 @@ module ActionController
1045
1060
  value.is_a?(Array) || value.is_a?(Parameters)
1046
1061
  end
1047
1062
 
1048
- EMPTY_ARRAY = []
1049
- EMPTY_HASH = {}
1063
+ EMPTY_ARRAY = [] # :nodoc:
1064
+ EMPTY_HASH = {} # :nodoc:
1050
1065
  def hash_filter(params, filter)
1051
1066
  filter = filter.with_indifferent_access
1052
1067
 
@@ -1067,7 +1082,7 @@ module ActionController
1067
1082
  end
1068
1083
  elsif non_scalar?(value)
1069
1084
  # Declaration { user: :name } or { user: [:name, :age, { address: ... }] }.
1070
- params[key] = each_element(value) do |element|
1085
+ params[key] = each_element(value, filter[key]) do |element|
1071
1086
  element.permit(*Array.wrap(filter[key]))
1072
1087
  end
1073
1088
  end
@@ -1184,7 +1199,15 @@ module ActionController
1184
1199
  # Returns a new ActionController::Parameters object that
1185
1200
  # has been instantiated with the <tt>request.parameters</tt>.
1186
1201
  def params
1187
- @_params ||= Parameters.new(request.parameters)
1202
+ @_params ||= begin
1203
+ context = {
1204
+ controller: self.class.name,
1205
+ action: action_name,
1206
+ request: request,
1207
+ params: request.filtered_parameters
1208
+ }
1209
+ Parameters.new(request.parameters, context)
1210
+ end
1188
1211
  end
1189
1212
 
1190
1213
  # Assigns the given +value+ to the +params+ hash. If +value+
@@ -2,10 +2,17 @@
2
2
 
3
3
  module ActionController
4
4
  module Testing
5
- extend ActiveSupport::Concern
6
-
7
5
  # Behavior specific to functional tests
8
6
  module Functional # :nodoc:
7
+ def clear_instance_variables_between_requests
8
+ if defined?(@_ivars)
9
+ new_ivars = instance_variables - @_ivars
10
+ new_ivars.each { |ivar| remove_instance_variable(ivar) }
11
+ end
12
+
13
+ @_ivars = instance_variables
14
+ end
15
+
9
16
  def recycle!
10
17
  @_url_options = nil
11
18
  self.formats = nil
@@ -4,12 +4,10 @@ module ActionController
4
4
  # Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing
5
5
  # the <tt>_routes</tt> method. Otherwise, an exception will be raised.
6
6
  #
7
- # In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
7
+ # In addition to AbstractController::UrlFor, this module accesses the HTTP layer to define
8
8
  # URL options like the +host+. In order to do so, this module requires the host class
9
- # to implement +env+ which needs to be Rack-compatible and +request+
10
- # which is either an instance of +ActionDispatch::Request+ or an object
11
- # that responds to the +host+, +optional_port+, +protocol+ and
12
- # +symbolized_path_parameter+ methods.
9
+ # to implement +env+ which needs to be Rack-compatible, and +request+ which
10
+ # returns an ActionDispatch::Request instance.
13
11
  #
14
12
  # class RootUrl
15
13
  # include ActionController::UrlFor