actionpack 6.0.4.1 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +241 -304
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/abstract_controller/base.rb +35 -2
  6. data/lib/abstract_controller/callbacks.rb +2 -2
  7. data/lib/abstract_controller/helpers.rb +105 -90
  8. data/lib/abstract_controller/rendering.rb +9 -9
  9. data/lib/abstract_controller/translation.rb +8 -2
  10. data/lib/abstract_controller.rb +1 -0
  11. data/lib/action_controller/api.rb +2 -2
  12. data/lib/action_controller/base.rb +4 -2
  13. data/lib/action_controller/caching.rb +0 -1
  14. data/lib/action_controller/log_subscriber.rb +3 -3
  15. data/lib/action_controller/metal/conditional_get.rb +10 -2
  16. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  17. data/lib/action_controller/metal/data_streaming.rb +1 -1
  18. data/lib/action_controller/metal/etag_with_template_digest.rb +2 -4
  19. data/lib/action_controller/metal/exceptions.rb +33 -0
  20. data/lib/action_controller/metal/feature_policy.rb +46 -0
  21. data/lib/action_controller/metal/head.rb +7 -4
  22. data/lib/action_controller/metal/helpers.rb +11 -1
  23. data/lib/action_controller/metal/http_authentication.rb +5 -3
  24. data/lib/action_controller/metal/implicit_render.rb +1 -1
  25. data/lib/action_controller/metal/instrumentation.rb +11 -9
  26. data/lib/action_controller/metal/live.rb +1 -1
  27. data/lib/action_controller/metal/logging.rb +20 -0
  28. data/lib/action_controller/metal/mime_responds.rb +6 -2
  29. data/lib/action_controller/metal/parameter_encoding.rb +35 -4
  30. data/lib/action_controller/metal/params_wrapper.rb +16 -11
  31. data/lib/action_controller/metal/redirecting.rb +1 -1
  32. data/lib/action_controller/metal/rendering.rb +6 -0
  33. data/lib/action_controller/metal/request_forgery_protection.rb +1 -1
  34. data/lib/action_controller/metal/rescue.rb +1 -1
  35. data/lib/action_controller/metal/strong_parameters.rb +103 -15
  36. data/lib/action_controller/metal.rb +2 -2
  37. data/lib/action_controller/renderer.rb +24 -13
  38. data/lib/action_controller/test_case.rb +62 -56
  39. data/lib/action_controller.rb +2 -3
  40. data/lib/action_dispatch/http/cache.rb +12 -10
  41. data/lib/action_dispatch/http/content_security_policy.rb +5 -1
  42. data/lib/action_dispatch/http/feature_policy.rb +168 -0
  43. data/lib/action_dispatch/http/filter_parameters.rb +1 -1
  44. data/lib/action_dispatch/http/filter_redirect.rb +1 -1
  45. data/lib/action_dispatch/http/headers.rb +3 -2
  46. data/lib/action_dispatch/http/mime_negotiation.rb +14 -8
  47. data/lib/action_dispatch/http/mime_type.rb +29 -16
  48. data/lib/action_dispatch/http/parameters.rb +1 -19
  49. data/lib/action_dispatch/http/request.rb +24 -8
  50. data/lib/action_dispatch/http/response.rb +17 -16
  51. data/lib/action_dispatch/http/url.rb +3 -2
  52. data/lib/action_dispatch/journey/formatter.rb +53 -28
  53. data/lib/action_dispatch/journey/gtg/builder.rb +22 -36
  54. data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
  55. data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -4
  56. data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
  57. data/lib/action_dispatch/journey/nodes/node.rb +4 -3
  58. data/lib/action_dispatch/journey/parser.rb +13 -13
  59. data/lib/action_dispatch/journey/parser.y +1 -1
  60. data/lib/action_dispatch/journey/path/pattern.rb +13 -18
  61. data/lib/action_dispatch/journey/route.rb +7 -18
  62. data/lib/action_dispatch/journey/router/utils.rb +6 -4
  63. data/lib/action_dispatch/journey/router.rb +26 -30
  64. data/lib/action_dispatch/journey.rb +0 -2
  65. data/lib/action_dispatch/middleware/actionable_exceptions.rb +1 -1
  66. data/lib/action_dispatch/middleware/cookies.rb +67 -32
  67. data/lib/action_dispatch/middleware/debug_exceptions.rb +8 -15
  68. data/lib/action_dispatch/middleware/debug_view.rb +1 -1
  69. data/lib/action_dispatch/middleware/exception_wrapper.rb +28 -16
  70. data/lib/action_dispatch/middleware/host_authorization.rb +29 -12
  71. data/lib/action_dispatch/middleware/remote_ip.rb +5 -4
  72. data/lib/action_dispatch/middleware/request_id.rb +4 -5
  73. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -2
  74. data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
  75. data/lib/action_dispatch/middleware/ssl.rb +9 -6
  76. data/lib/action_dispatch/middleware/stack.rb +18 -0
  77. data/lib/action_dispatch/middleware/static.rb +154 -93
  78. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +18 -0
  79. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +2 -5
  80. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +2 -2
  81. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -3
  82. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +88 -8
  83. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  84. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +12 -1
  85. data/lib/action_dispatch/railtie.rb +3 -2
  86. data/lib/action_dispatch/request/session.rb +2 -8
  87. data/lib/action_dispatch/request/utils.rb +26 -2
  88. data/lib/action_dispatch/routing/inspector.rb +8 -7
  89. data/lib/action_dispatch/routing/mapper.rb +102 -71
  90. data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -19
  91. data/lib/action_dispatch/routing/redirection.rb +3 -3
  92. data/lib/action_dispatch/routing/route_set.rb +49 -41
  93. data/lib/action_dispatch/system_test_case.rb +29 -24
  94. data/lib/action_dispatch/system_testing/browser.rb +33 -27
  95. data/lib/action_dispatch/system_testing/driver.rb +6 -7
  96. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +47 -6
  97. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +4 -7
  98. data/lib/action_dispatch/testing/assertions/response.rb +2 -4
  99. data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
  100. data/lib/action_dispatch/testing/assertions.rb +1 -1
  101. data/lib/action_dispatch/testing/integration.rb +38 -27
  102. data/lib/action_dispatch/testing/test_process.rb +29 -4
  103. data/lib/action_dispatch/testing/test_request.rb +3 -3
  104. data/lib/action_dispatch.rb +3 -2
  105. data/lib/action_pack/gem_version.rb +3 -3
  106. data/lib/action_pack.rb +1 -1
  107. metadata +23 -24
  108. data/lib/action_controller/metal/force_ssl.rb +0 -58
  109. data/lib/action_dispatch/http/parameter_filter.rb +0 -12
  110. data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
  111. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  112. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -119
@@ -12,11 +12,13 @@ module ActionController
12
12
  end
13
13
 
14
14
  def setup_param_encode # :nodoc:
15
- @_parameter_encodings = {}
15
+ @_parameter_encodings = Hash.new { |h, k| h[k] = {} }
16
16
  end
17
17
 
18
- def binary_params_for?(action) # :nodoc:
19
- @_parameter_encodings[action.to_s]
18
+ def action_encoding_template(action) # :nodoc:
19
+ if @_parameter_encodings.has_key?(action.to_s)
20
+ @_parameter_encodings[action.to_s]
21
+ end
20
22
  end
21
23
 
22
24
  # Specify that a given action's parameters should all be encoded as
@@ -44,7 +46,36 @@ module ActionController
44
46
  # encoded as ASCII-8BIT. This is useful in the case where an application
45
47
  # must handle data but encoding of the data is unknown, like file system data.
46
48
  def skip_parameter_encoding(action)
47
- @_parameter_encodings[action.to_s] = true
49
+ @_parameter_encodings[action.to_s] = Hash.new { Encoding::ASCII_8BIT }
50
+ end
51
+
52
+ # Specify the encoding for a parameter on an action.
53
+ # If not specified the default is UTF-8.
54
+ #
55
+ # You can specify a binary (ASCII_8BIT) parameter with:
56
+ #
57
+ # class RepositoryController < ActionController::Base
58
+ # # This specifies that file_path is not UTF-8 and is instead ASCII_8BIT
59
+ # param_encoding :show, :file_path, Encoding::ASCII_8BIT
60
+ #
61
+ # def show
62
+ # @repo = Repository.find_by_filesystem_path params[:file_path]
63
+ #
64
+ # # params[:repo_name] remains UTF-8 encoded
65
+ # @repo_name = params[:repo_name]
66
+ # end
67
+ #
68
+ # def index
69
+ # @repositories = Repository.all
70
+ # end
71
+ # end
72
+ #
73
+ # The file_path parameter on the show action would be encoded as ASCII-8BIT,
74
+ # but all other arguments will remain UTF-8 encoded.
75
+ # This is useful in the case where an application must handle data
76
+ # but encoding of the data is unknown, like file system data.
77
+ def param_encoding(action, param, encoding)
78
+ @_parameter_encodings[action.to_s][param.to_s] = encoding
48
79
  end
49
80
  end
50
81
  end
@@ -107,10 +107,14 @@ module ActionController
107
107
 
108
108
  unless super || exclude
109
109
  if m.respond_to?(:attribute_names) && m.attribute_names.any?
110
+ self.include = m.attribute_names
111
+
110
112
  if m.respond_to?(:stored_attributes) && !m.stored_attributes.empty?
111
- self.include = m.attribute_names + m.stored_attributes.values.flatten.map(&:to_s)
112
- else
113
- self.include = m.attribute_names
113
+ self.include += m.stored_attributes.values.flatten.map(&:to_s)
114
+ end
115
+
116
+ if m.respond_to?(:attribute_aliases) && m.attribute_aliases.any?
117
+ self.include += m.attribute_aliases.keys
114
118
  end
115
119
 
116
120
  if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
@@ -151,7 +155,7 @@ module ActionController
151
155
  # try to find Foo::Bar::User, Foo::User and finally User.
152
156
  def _default_wrap_model
153
157
  return nil if klass.anonymous?
154
- model_name = klass.name.sub(/Controller$/, "").classify
158
+ model_name = klass.name.delete_suffix("Controller").classify
155
159
 
156
160
  begin
157
161
  if model_klass = model_name.safe_constantize
@@ -189,7 +193,7 @@ module ActionController
189
193
  #
190
194
  # wrap_parameters Person
191
195
  # # wraps parameters by determining the wrapper key from Person class
192
- # (+person+, in this case) and the list of attribute names
196
+ # # (+person+, in this case) and the list of attribute names
193
197
  #
194
198
  # wrap_parameters include: [:username, :title]
195
199
  # # wraps only +:username+ and +:title+ attributes from parameters.
@@ -240,7 +244,7 @@ module ActionController
240
244
 
241
245
  # Performs parameters wrapping upon the request. Called automatically
242
246
  # by the metal call stack.
243
- def process_action(*args)
247
+ def process_action(*)
244
248
  _perform_parameter_wrapping if _wrapper_enabled?
245
249
  super
246
250
  end
@@ -264,9 +268,11 @@ module ActionController
264
268
  def _extract_parameters(parameters)
265
269
  if include_only = _wrapper_options.include
266
270
  parameters.slice(*include_only)
271
+ elsif _wrapper_options.exclude
272
+ exclude = _wrapper_options.exclude + EXCLUDE_PARAMETERS
273
+ parameters.except(*exclude)
267
274
  else
268
- exclude = _wrapper_options.exclude || []
269
- parameters.except(*(exclude + EXCLUDE_PARAMETERS))
275
+ parameters.except(*EXCLUDE_PARAMETERS)
270
276
  end
271
277
  end
272
278
 
@@ -275,10 +281,7 @@ module ActionController
275
281
  return false unless request.has_content_type?
276
282
 
277
283
  ref = request.content_mime_type.ref
278
-
279
284
  _wrapper_formats.include?(ref) && _wrapper_key && !request.parameters.key?(_wrapper_key)
280
- rescue ActionDispatch::Http::Parameters::ParseError
281
- false
282
285
  end
283
286
 
284
287
  def _perform_parameter_wrapping
@@ -292,6 +295,8 @@ module ActionController
292
295
 
293
296
  # This will display the wrapped hash in the log file.
294
297
  request.filtered_parameters.merge! wrapped_filtered_hash
298
+ rescue ActionDispatch::Http::Parameters::ParseError
299
+ # swallow parse error exception
295
300
  end
296
301
  end
297
302
  end
@@ -85,7 +85,7 @@ module ActionController
85
85
  # * <tt>:fallback_location</tt> - The default fallback location that will be used on missing +Referer+ header.
86
86
  # * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
87
87
  #
88
- # All other options that can be passed to <tt>redirect_to</tt> are accepted as
88
+ # All other options that can be passed to #redirect_to are accepted as
89
89
  # options and the behavior is identical.
90
90
  def redirect_back(fallback_location:, allow_other_host: true, **args)
91
91
  referer = request.headers["Referer"]
@@ -77,6 +77,12 @@ module ActionController
77
77
  end
78
78
  end
79
79
 
80
+ def _set_vary_header
81
+ if self.headers["Vary"].blank? && request.should_apply_vary_header?
82
+ self.headers["Vary"] = "Accept"
83
+ end
84
+ end
85
+
80
86
  # Normalize arguments by catching blocks and setting them on :update.
81
87
  def _normalize_args(action = nil, options = {}, &blk)
82
88
  options = super
@@ -386,7 +386,7 @@ module ActionController #:nodoc:
386
386
  if per_form_csrf_tokens
387
387
  correct_token = per_form_csrf_token(
388
388
  session,
389
- normalize_action_path(request.fullpath),
389
+ request.path.chomp("/"),
390
390
  request.request_method
391
391
  )
392
392
 
@@ -18,7 +18,7 @@ module ActionController #:nodoc:
18
18
  end
19
19
 
20
20
  private
21
- def process_action(*args)
21
+ def process_action(*)
22
22
  super
23
23
  rescue Exception => exception
24
24
  request.env["action_dispatch.show_detailed_exceptions"] ||= show_detailed_exceptions?
@@ -19,12 +19,36 @@ module ActionController
19
19
  # params.require(:a)
20
20
  # # => ActionController::ParameterMissing: param is missing or the value is empty: a
21
21
  class ParameterMissing < KeyError
22
- attr_reader :param # :nodoc:
22
+ attr_reader :param, :keys # :nodoc:
23
23
 
24
- def initialize(param) # :nodoc:
24
+ def initialize(param, keys = nil) # :nodoc:
25
25
  @param = param
26
+ @keys = keys
26
27
  super("param is missing or the value is empty: #{param}")
27
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
28
52
  end
29
53
 
30
54
  # Raised when a supplied parameter is not expected and
@@ -180,6 +204,14 @@ module ActionController
180
204
  #
181
205
  # Returns true if the given key is present in the parameters.
182
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
+
183
215
  ##
184
216
  # :method: keys
185
217
  #
@@ -211,7 +243,7 @@ module ActionController
211
243
  # values()
212
244
  #
213
245
  # Returns a new array of the values of the parameters.
214
- delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?,
246
+ delegate :keys, :key?, :has_key?, :member?, :values, :has_value?, :value?, :empty?, :include?,
215
247
  :as_json, :to_s, :each_key, to: :@parameters
216
248
 
217
249
  # By default, never raise an UnpermittedParameters exception if these
@@ -220,9 +252,15 @@ module ActionController
220
252
  # to change these is to specify `always_permitted_parameters` in your
221
253
  # config. For instance:
222
254
  #
223
- # config.always_permitted_parameters = %w( controller action format )
255
+ # config.action_controller.always_permitted_parameters = %w( controller action format )
224
256
  cattr_accessor :always_permitted_parameters, default: %w( controller action )
225
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
+
226
264
  # Returns a new instance of <tt>ActionController::Parameters</tt>.
227
265
  # Also, sets the +permitted+ attribute to the default value of
228
266
  # <tt>ActionController::Parameters.permit_all_parameters</tt>.
@@ -253,6 +291,11 @@ module ActionController
253
291
  @parameters == other
254
292
  end
255
293
  end
294
+ alias eql? ==
295
+
296
+ def hash
297
+ [@parameters.hash, @permitted].hash
298
+ end
256
299
 
257
300
  # Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
258
301
  # representation of the parameters with all unpermitted keys removed.
@@ -341,6 +384,7 @@ module ActionController
341
384
  # Convert all hashes in values into parameters, then yield each pair in
342
385
  # the same way as <tt>Hash#each_pair</tt>.
343
386
  def each_pair(&block)
387
+ return to_enum(__callee__) unless block_given?
344
388
  @parameters.each_pair do |key, value|
345
389
  yield [key, convert_hashes_to_parameters(key, value)]
346
390
  end
@@ -352,6 +396,7 @@ module ActionController
352
396
  # Convert all hashes in values into parameters, then yield each value in
353
397
  # the same way as <tt>Hash#each_value</tt>.
354
398
  def each_value(&block)
399
+ return to_enum(:each_value) unless block_given?
355
400
  @parameters.each_pair do |key, value|
356
401
  yield convert_hashes_to_parameters(key, value)
357
402
  end
@@ -459,7 +504,7 @@ module ActionController
459
504
  if value.present? || value == false
460
505
  value
461
506
  else
462
- raise ParameterMissing.new(key)
507
+ raise ParameterMissing.new(key, @parameters.keys)
463
508
  end
464
509
  end
465
510
 
@@ -596,7 +641,7 @@ module ActionController
596
641
  if block_given?
597
642
  yield
598
643
  else
599
- args.fetch(0) { raise ActionController::ParameterMissing.new(key) }
644
+ args.fetch(0) { raise ActionController::ParameterMissing.new(key, @parameters.keys) }
600
645
  end
601
646
  }
602
647
  )
@@ -691,6 +736,23 @@ module ActionController
691
736
  self
692
737
  end
693
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
+
694
756
  # Deletes a key-value pair from +Parameters+ and returns the value. If
695
757
  # +key+ is not found, returns +nil+ (or, with optional code block, yields
696
758
  # +key+ and returns the result). Cf. +#extract!+, which returns the
@@ -725,6 +787,28 @@ module ActionController
725
787
  end
726
788
  alias_method :delete_if, :reject!
727
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
+
728
812
  # Returns values that were assigned to the given +keys+. Note that all the
729
813
  # +Hash+ objects will be converted to <tt>ActionController::Parameters</tt>.
730
814
  def values_at(*keys)
@@ -771,7 +855,7 @@ module ActionController
771
855
  end
772
856
 
773
857
  def inspect
774
- "<#{self.class} #{@parameters} permitted: #{@permitted}>"
858
+ "#<#{self.class} #{@parameters} permitted: #{@permitted}>"
775
859
  end
776
860
 
777
861
  def self.hook_into_yaml_loading # :nodoc:
@@ -813,8 +897,14 @@ module ActionController
813
897
 
814
898
  attr_writer :permitted
815
899
 
816
- def fields_for_style?
817
- @parameters.all? { |k, v| k =~ /\A-?\d+\z/ && (v.is_a?(Hash) || v.is_a?(Parameters)) }
900
+ def nested_attributes?
901
+ @parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
902
+ end
903
+
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
818
908
  end
819
909
 
820
910
  private
@@ -859,15 +949,13 @@ module ActionController
859
949
  end
860
950
  end
861
951
 
862
- def each_element(object)
952
+ def each_element(object, &block)
863
953
  case object
864
954
  when Array
865
955
  object.grep(Parameters).map { |el| yield el }.compact
866
956
  when Parameters
867
- if object.fields_for_style?
868
- hash = object.class.new
869
- object.each { |k, v| hash[k] = yield v }
870
- hash
957
+ if object.nested_attributes?
958
+ object.each_nested_attribute(&block)
871
959
  else
872
960
  yield object
873
961
  end
@@ -895,7 +983,7 @@ module ActionController
895
983
  # --- Filtering ----------------------------------------------------------
896
984
  #
897
985
 
898
- # This is a white list of permitted scalar types that includes the ones
986
+ # This is a list of permitted scalar types that includes the ones
899
987
  # supported in XML and JSON requests.
900
988
  #
901
989
  # This list is in particular used to filter ordinary requests, String goes
@@ -126,7 +126,7 @@ module ActionController
126
126
  # ==== Returns
127
127
  # * <tt>string</tt>
128
128
  def self.controller_name
129
- @controller_name ||= name.demodulize.sub(/Controller$/, "").underscore
129
+ @controller_name ||= (name.demodulize.delete_suffix("Controller").underscore unless anonymous?)
130
130
  end
131
131
 
132
132
  def self.make_response!(request)
@@ -135,7 +135,7 @@ module ActionController
135
135
  end
136
136
  end
137
137
 
138
- def self.binary_params_for?(action) # :nodoc:
138
+ def self.action_encoding_template(action) # :nodoc:
139
139
  false
140
140
  end
141
141
 
@@ -65,7 +65,7 @@ module ActionController
65
65
  def initialize(controller, env, defaults)
66
66
  @controller = controller
67
67
  @defaults = defaults
68
- @env = normalize_keys defaults.merge(env)
68
+ @env = normalize_keys defaults, env
69
69
  end
70
70
 
71
71
  # Render templates with any options from ActionController::Base#render_to_string.
@@ -82,8 +82,12 @@ module ActionController
82
82
  # need to call <tt>.to_json</tt> on the object you want to render.
83
83
  # * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>.
84
84
  #
85
- # If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, the default is
86
- # to render a partial and use the second parameter as the locals hash.
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.
87
91
  def render(*args)
88
92
  raise "missing controller" unless controller
89
93
 
@@ -95,11 +99,18 @@ module ActionController
95
99
  instance.set_response! controller.make_response!(request)
96
100
  instance.render_to_string(*args)
97
101
  end
102
+ alias_method :render_to_string, :render # :nodoc:
98
103
 
99
104
  private
100
- def normalize_keys(env)
105
+ def normalize_keys(defaults, env)
101
106
  new_env = {}
102
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
+
103
114
  new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
104
115
  new_env
105
116
  end
@@ -112,19 +123,19 @@ module ActionController
112
123
  input: "rack.input"
113
124
  }
114
125
 
115
- IDENTITY = ->(_) { _ }
116
-
117
- RACK_VALUE_TRANSLATION = {
118
- https: ->(v) { v ? "on" : "off" },
119
- method: ->(v) { -v.upcase },
120
- }
121
-
122
126
  def rack_key_for(key)
123
- RACK_KEY_TRANSLATION.fetch(key, key.to_s)
127
+ RACK_KEY_TRANSLATION[key] || key.to_s
124
128
  end
125
129
 
126
130
  def rack_value_for(key, value)
127
- RACK_VALUE_TRANSLATION.fetch(key, IDENTITY).call value
131
+ case key
132
+ when :https
133
+ value ? "on" : "off"
134
+ when :method
135
+ -value.upcase
136
+ else
137
+ value
138
+ end
128
139
  end
129
140
  end
130
141
  end