aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r--actionpack/lib/action_controller/api.rb10
-rw-r--r--actionpack/lib/action_controller/api/api_rendering.rb2
-rw-r--r--actionpack/lib/action_controller/base.rb18
-rw-r--r--actionpack/lib/action_controller/caching.rb2
-rw-r--r--actionpack/lib/action_controller/form_builder.rb2
-rw-r--r--actionpack/lib/action_controller/log_subscriber.rb8
-rw-r--r--actionpack/lib/action_controller/metal.rb11
-rw-r--r--actionpack/lib/action_controller/metal/basic_implicit_render.rb2
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb7
-rw-r--r--actionpack/lib/action_controller/metal/content_security_policy.rb26
-rw-r--r--actionpack/lib/action_controller/metal/cookies.rb2
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb12
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_flash.rb6
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_template_digest.rb5
-rw-r--r--actionpack/lib/action_controller/metal/exceptions.rb5
-rw-r--r--actionpack/lib/action_controller/metal/flash.rb5
-rw-r--r--actionpack/lib/action_controller/metal/force_ssl.rb18
-rw-r--r--actionpack/lib/action_controller/metal/head.rb2
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb7
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb19
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb8
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb12
-rw-r--r--actionpack/lib/action_controller/metal/live.rb12
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb6
-rw-r--r--actionpack/lib/action_controller/metal/parameter_encoding.rb4
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb36
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb35
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb7
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb6
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb55
-rw-r--r--actionpack/lib/action_controller/metal/rescue.rb10
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb6
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb256
-rw-r--r--actionpack/lib/action_controller/metal/testing.rb8
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb4
-rw-r--r--actionpack/lib/action_controller/railtie.rb34
-rw-r--r--actionpack/lib/action_controller/railties/helpers.rb2
-rw-r--r--actionpack/lib/action_controller/renderer.rb8
-rw-r--r--actionpack/lib/action_controller/template_assertions.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb16
40 files changed, 499 insertions, 197 deletions
diff --git a/actionpack/lib/action_controller/api.rb b/actionpack/lib/action_controller/api.rb
index 5cd8d77ddb..b192e496de 100644
--- a/actionpack/lib/action_controller/api.rb
+++ b/actionpack/lib/action_controller/api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_view"
require "action_controller"
require "action_controller/log_subscriber"
@@ -81,10 +83,9 @@ module ActionController
# end
# end
#
- # Quite straightforward. Make sure to check the modules included in
- # <tt>ActionController::Base</tt> if you want to use any other
- # functionality that is not provided by <tt>ActionController::API</tt>
- # out of the box.
+ # Make sure to check the modules included in <tt>ActionController::Base</tt>
+ # if you want to use any other functionality that is not provided
+ # by <tt>ActionController::API</tt> out of the box.
class API < Metal
abstract!
@@ -142,6 +143,7 @@ module ActionController
include mod
end
+ ActiveSupport.run_load_hooks(:action_controller_api, self)
ActiveSupport.run_load_hooks(:action_controller, self)
end
end
diff --git a/actionpack/lib/action_controller/api/api_rendering.rb b/actionpack/lib/action_controller/api/api_rendering.rb
index 3a08d28c39..aca5265313 100644
--- a/actionpack/lib/action_controller/api/api_rendering.rb
+++ b/actionpack/lib/action_controller/api/api_rendering.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module ApiRendering
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index ca8066cd82..204a3d400c 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_view"
require "action_controller/log_subscriber"
require "action_controller/metal/params_wrapper"
@@ -8,7 +10,7 @@ module ActionController
# on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
#
# By default, only the ApplicationController in a \Rails application inherits from <tt>ActionController::Base</tt>. All other
- # controllers in turn inherit from ApplicationController. This gives you one class to configure things such as
+ # controllers inherit from ApplicationController. This gives you one class to configure things such as
# request forgery protection and filtering of sensitive request parameters.
#
# A sample controller could look like this:
@@ -30,7 +32,7 @@ module ActionController
#
# Unlike index, the create action will not render a template. After performing its main purpose (creating a
# new post), it initiates a redirect instead. This redirect works by returning an external
- # "302 Moved" HTTP response that takes the user to the index action.
+ # <tt>302 Moved</tt> HTTP response that takes the user to the index action.
#
# These two methods represent the two basic action archetypes used in Action Controllers: Get-and-show and do-and-redirect.
# Most actions are variations on these themes.
@@ -59,7 +61,7 @@ module ActionController
# <input type="text" name="post[name]" value="david">
# <input type="text" name="post[address]" value="hyacintvej">
#
- # A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
+ # A request coming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
# If the address input had been named <tt>post[address][street]</tt>, the <tt>params</tt> would have included
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
#
@@ -74,7 +76,7 @@ module ActionController
#
# session[:person] = Person.authenticate(user_name, password)
#
- # And retrieved again through the same hash:
+ # You can retrieve it again through the same hash:
#
# Hello #{session[:person]}
#
@@ -223,6 +225,7 @@ module ActionController
Flash,
FormBuilder,
RequestForgeryProtection,
+ ContentSecurityPolicy,
ForceSSL,
Streaming,
DataStreaming,
@@ -261,6 +264,13 @@ module ActionController
PROTECTED_IVARS
end
+ def self.make_response!(request)
+ ActionDispatch::Response.create.tap do |res|
+ res.request = request
+ end
+ end
+
+ ActiveSupport.run_load_hooks(:action_controller_base, self)
ActiveSupport.run_load_hooks(:action_controller, self)
end
end
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index 954265ad97..97775d1dc8 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# \Caching is a cheap way of speeding up slow applications by keeping the result of
# calculations, renderings, and database calls around for subsequent requests.
diff --git a/actionpack/lib/action_controller/form_builder.rb b/actionpack/lib/action_controller/form_builder.rb
index f2656ca894..09d2ac1837 100644
--- a/actionpack/lib/action_controller/form_builder.rb
+++ b/actionpack/lib/action_controller/form_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# Override the default form builder for all views rendered by this
# controller and any of its descendants. Accepts a subclass of
diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb
index d29a5fe68f..14f41eb55f 100644
--- a/actionpack/lib/action_controller/log_subscriber.rb
+++ b/actionpack/lib/action_controller/log_subscriber.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
class LogSubscriber < ActiveSupport::LogSubscriber
INTERNAL_PARAMS = %w(controller action format _method only_path)
@@ -24,7 +26,7 @@ module ActionController
exception_class_name = payload[:exception].first
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
end
- message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
+ message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms".dup
message << " (#{additions.join(" | ".freeze)})" unless additions.empty?
message << "\n\n" if defined?(Rails.env) && Rails.env.development?
@@ -60,9 +62,9 @@ module ActionController
class_eval <<-METHOD, __FILE__, __LINE__ + 1
def #{method}(event)
return unless logger.info? && ActionController::Base.enable_fragment_cache_logging
- key_or_path = event.payload[:key] || event.payload[:path]
+ key = ActiveSupport::Cache.expand_cache_key(event.payload[:key] || event.payload[:path])
human_name = #{method.to_s.humanize.inspect}
- info("\#{human_name} \#{key_or_path} (\#{event.duration.round(1)}ms)")
+ info("\#{human_name} \#{key} (\#{event.duration.round(1)}ms)")
end
METHOD
end
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 337718afc0..457884ea08 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/array/extract_options"
require "action_dispatch/middleware/stack"
require "action_dispatch/http/request"
@@ -129,7 +131,7 @@ module ActionController
end
def self.make_response!(request)
- ActionDispatch::Response.create.tap do |res|
+ ActionDispatch::Response.new.tap do |res|
res.request = request
end
end
@@ -138,7 +140,7 @@ module ActionController
false
end
- # Delegates to the class' <tt>controller_name</tt>
+ # Delegates to the class' <tt>controller_name</tt>.
def controller_name
self.class.controller_name
end
@@ -208,8 +210,7 @@ module ActionController
@_request.reset_session
end
- class_attribute :middleware_stack
- self.middleware_stack = ActionController::MiddlewareStack.new
+ class_attribute :middleware_stack, default: ActionController::MiddlewareStack.new
def self.inherited(base) # :nodoc:
base.middleware_stack = middleware_stack.dup
@@ -244,7 +245,7 @@ module ActionController
end
end
- # Direct dispatch to the controller. Instantiates the controller, then
+ # Direct dispatch to the controller. Instantiates the controller, then
# executes the action named +name+.
def self.dispatch(name, req, res)
if middleware_stack.any?
diff --git a/actionpack/lib/action_controller/metal/basic_implicit_render.rb b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
index cef65a362c..2dc990f303 100644
--- a/actionpack/lib/action_controller/metal/basic_implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module BasicImplicitRender # :nodoc:
def send_action(method, *args)
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index eb636fa3f6..06b6a95ff8 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/keys"
module ActionController
@@ -7,8 +9,7 @@ module ActionController
include Head
included do
- class_attribute :etaggers
- self.etaggers = []
+ class_attribute :etaggers, default: []
end
module ClassMethods
@@ -227,7 +228,7 @@ module ActionController
# expires_in 3.hours, public: true, must_revalidate: true
#
# This method will overwrite an existing Cache-Control header.
- # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
+ # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
#
# The method will also ensure an HTTP Date header for client compatibility.
def expires_in(seconds, options = {})
diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb
new file mode 100644
index 0000000000..48a7109bea
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/content_security_policy.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module ActionController #:nodoc:
+ module ContentSecurityPolicy
+ # TODO: Documentation
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def content_security_policy(**options, &block)
+ before_action(options) do
+ if block_given?
+ policy = request.content_security_policy.clone
+ yield policy
+ request.content_security_policy = policy
+ end
+ end
+ end
+
+ def content_security_policy_report_only(report_only = true, **options)
+ before_action(options) do
+ request.content_security_policy_report_only = report_only
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb
index 44925641a1..ff46966693 100644
--- a/actionpack/lib/action_controller/metal/cookies.rb
+++ b/actionpack/lib/action_controller/metal/cookies.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController #:nodoc:
module Cookies
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 731e03e2fc..5a82ccf668 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_controller/metal/exceptions"
module ActionController #:nodoc:
@@ -54,14 +56,14 @@ module ActionController #:nodoc:
#
# Read about the other Content-* HTTP headers if you'd like to
# provide the user with more information (such as Content-Description) in
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
+ # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
#
# Also be aware that the document may be cached by proxies and browsers.
# The Pragma and Cache-Control headers declare how the file may be cached
# by intermediaries. They default to require clients to validate with
# the server before releasing cached responses. See
- # http://www.mnot.net/cache_docs/ for an overview of web caching and
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
+ # https://www.mnot.net/cache_docs/ for an overview of web caching and
+ # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
# for the Cache-Control header spec.
def send_file(path, options = {}) #:doc:
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) && File.readable?(path)
@@ -111,10 +113,10 @@ module ActionController #:nodoc:
def send_file_headers!(options)
type_provided = options.has_key?(:type)
- self.content_type = DEFAULT_SEND_FILE_TYPE
+ content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
+ self.content_type = content_type
response.sending_file = true
- content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
raise ArgumentError, ":type option required" if content_type.nil?
if content_type.is_a?(Symbol)
diff --git a/actionpack/lib/action_controller/metal/etag_with_flash.rb b/actionpack/lib/action_controller/metal/etag_with_flash.rb
index 474d75f02e..38899e2f16 100644
--- a/actionpack/lib/action_controller/metal/etag_with_flash.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_flash.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module ActionController
# When you're using the flash, it's generally used as a conditional on the view.
# This means the content of the view depends on the flash. Which in turn means
- # that the etag for a response should be computed with the content of the flash
+ # that the ETag for a response should be computed with the content of the flash
# in mind. This does that by including the content of the flash as a component
- # in the etag that's generated for a response.
+ # in the ETag that's generated for a response.
module EtagWithFlash
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
index 798564db96..640c75536e 100644
--- a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# When our views change, they should bubble up into HTTP cache freshness
# and bust browser caches. So the template digest for the current action
@@ -22,8 +24,7 @@ module ActionController
include ActionController::ConditionalGet
included do
- class_attribute :etag_with_template_digest
- self.etag_with_template_digest = true
+ class_attribute :etag_with_template_digest, default: true
ActiveSupport.on_load :action_view, yield: true do
etag do |options|
diff --git a/actionpack/lib/action_controller/metal/exceptions.rb b/actionpack/lib/action_controller/metal/exceptions.rb
index 175dd9eb9e..a65857d6ef 100644
--- a/actionpack/lib/action_controller/metal/exceptions.rb
+++ b/actionpack/lib/action_controller/metal/exceptions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
class ActionControllerError < StandardError #:nodoc:
end
@@ -32,9 +34,6 @@ module ActionController
class NotImplemented < MethodNotAllowed #:nodoc:
end
- class UnknownController < ActionControllerError #:nodoc:
- end
-
class MissingFile < ActionControllerError #:nodoc:
end
diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb
index 347fbf0e74..5115c2fadf 100644
--- a/actionpack/lib/action_controller/metal/flash.rb
+++ b/actionpack/lib/action_controller/metal/flash.rb
@@ -1,10 +1,11 @@
+# frozen_string_literal: true
+
module ActionController #:nodoc:
module Flash
extend ActiveSupport::Concern
included do
- class_attribute :_flash_types, instance_accessor: false
- self._flash_types = []
+ class_attribute :_flash_types, instance_accessor: false, default: []
delegate :flash, to: :request
add_flash_types(:alert, :notice)
diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb
index 9d43e752ac..7de500d119 100644
--- a/actionpack/lib/action_controller/metal/force_ssl.rb
+++ b/actionpack/lib/action_controller/metal/force_ssl.rb
@@ -1,18 +1,20 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/except"
require "active_support/core_ext/hash/slice"
module ActionController
- # This module provides a method which will redirect the browser to use HTTPS
- # protocol. This will ensure that user's sensitive information will be
+ # This module provides a method which will redirect the browser to use the secured HTTPS
+ # protocol. This will ensure that users' sensitive information will be
# transferred safely over the internet. You _should_ always force the browser
# to use HTTPS when you're transferring sensitive information such as
# user authentication, account information, or credit card information.
#
# Note that if you are really concerned about your application security,
# you might consider using +config.force_ssl+ in your config file instead.
- # That will ensure all the data transferred via HTTPS protocol and prevent
- # the user from getting their session hijacked when accessing the site over
- # unsecured HTTP protocol.
+ # That will ensure all the data is transferred via HTTPS, and will
+ # prevent the user from getting their session hijacked when accessing the
+ # site over unsecured HTTP protocol.
module ForceSSL
extend ActiveSupport::Concern
include AbstractController::Callbacks
@@ -23,7 +25,7 @@ module ActionController
module ClassMethods
# Force the request to this particular controller or specified actions to be
- # under HTTPS protocol.
+ # through the HTTPS protocol.
#
# If you need to disable this for any reason (e.g. development) then you can use
# an +:if+ or +:unless+ condition.
@@ -37,7 +39,7 @@ module ActionController
# end
#
# ==== URL Options
- # You can pass any of the following options to affect the redirect url
+ # You can pass any of the following options to affect the redirect URL
# * <tt>host</tt> - Redirect to a different host name
# * <tt>subdomain</tt> - Redirect to a different subdomain
# * <tt>domain</tt> - Redirect to a different domain
@@ -71,7 +73,7 @@ module ActionController
# Redirect the existing request to use the HTTPS protocol.
#
# ==== Parameters
- # * <tt>host_or_options</tt> - Either a host name or any of the url &
+ # * <tt>host_or_options</tt> - Either a host name or any of the URL and
# redirect options available to the <tt>force_ssl</tt> method.
def force_ssl_redirect(host_or_options = nil)
unless request.ssl?
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index 0c50894bce..bac9bc5e5f 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Head
# Returns a response that has no content (merely headers). The options
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 476d081239..22c84e440b 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# The \Rails framework provides a large number of helpers for working with assets, dates, forms,
# numbers and model objects, to name a few. These helpers are available to all templates
@@ -53,9 +55,8 @@ module ActionController
include AbstractController::Helpers
included do
- class_attribute :helpers_path, :include_all_helpers
- self.helpers_path ||= []
- self.include_all_helpers = true
+ class_attribute :helpers_path, default: []
+ class_attribute :include_all_helpers, default: true
end
module ClassMethods
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 0575360068..01676f3237 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "base64"
require "active_support/security_utils"
@@ -70,10 +72,10 @@ module ActionController
before_action(options.except(:name, :password, :realm)) do
authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
# This comparison uses & so that it doesn't short circuit and
- # uses `variable_size_secure_compare` so that length information
+ # uses `secure_compare` so that length information
# isn't leaked.
- ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
- ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
+ ActiveSupport::SecurityUtils.secure_compare(name, options[:name]) &
+ ActiveSupport::SecurityUtils.secure_compare(password, options[:password])
end
end
end
@@ -246,7 +248,7 @@ module ActionController
def decode_credentials(header)
ActiveSupport::HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/, "").split(",").map do |pair|
key, value = pair.split("=", 2)
- [key.strip, value.to_s.gsub(/^"|"$/, "").delete('\'')]
+ [key.strip, value.to_s.gsub(/^"|"$/, "").delete("'")]
end]
end
@@ -348,10 +350,7 @@ module ActionController
# authenticate_or_request_with_http_token do |token, options|
# # Compare the tokens in a time-constant manner, to mitigate
# # timing attacks.
- # ActiveSupport::SecurityUtils.secure_compare(
- # ::Digest::SHA256.hexdigest(token),
- # ::Digest::SHA256.hexdigest(TOKEN)
- # )
+ # ActiveSupport::SecurityUtils.secure_compare(token, TOKEN)
# end
# end
# end
@@ -445,7 +444,7 @@ module ActionController
end
end
- # Parses the token and options out of the token authorization header.
+ # Parses the token and options out of the token Authorization header.
# The value for the Authorization header is expected to have the prefix
# <tt>"Token"</tt> or <tt>"Bearer"</tt>. If the header looks like this:
# Authorization: Token token="abc", nonce="def"
@@ -475,7 +474,7 @@ module ActionController
# This removes the <tt>"</tt> characters wrapping the value.
def rewrite_param_values(array_params)
- array_params.each { |param| (param[1] || "").gsub! %r/^"|"$/, "" }
+ array_params.each { |param| (param[1] || "".dup).gsub! %r/^"|"$/, "" }
end
# This method takes an authorization body and splits up the key-value
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index dde924e682..ac0c127cdc 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -1,12 +1,14 @@
+# frozen_string_literal: true
+
module ActionController
# Handles implicit rendering for a controller action that does not
# explicitly respond with +render+, +respond_to+, +redirect+, or +head+.
#
- # For API controllers, the implicit response is always 204 No Content.
+ # For API controllers, the implicit response is always <tt>204 No Content</tt>.
#
# For all other controllers, we use these heuristics to decide whether to
# render a template, raise an error for a missing template, or respond with
- # 204 No Content:
+ # <tt>204 No Content</tt>:
#
# First, if we DO find a template, it's rendered. Template lookup accounts
# for the action name, locales, format, variant, template handlers, and more
@@ -23,7 +25,7 @@ module ActionController
# <tt>ActionView::UnknownFormat</tt> with an explanation.
#
# Finally, if we DON'T find a template AND the request isn't a browser page
- # load, then we implicitly respond with 204 No Content.
+ # load, then we implicitly respond with <tt>204 No Content</tt>.
module ImplicitRender
# :stopdoc:
include BasicImplicitRender
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 924686218f..be9449629f 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
require "benchmark"
require "abstract_controller/logger"
module ActionController
# Adds instrumentation to several ends in ActionController::Base. It also provides
- # some hooks related with process_action, this allows an ORM like Active Record
+ # some hooks related with process_action. This allows an ORM like Active Record
# and/or DataMapper to plug in ActionController and show related information.
#
# Check ActiveRecord::Railties::ControllerRuntime for an example.
@@ -81,16 +83,13 @@ module ActionController
# def cleanup_view_runtime
# super - time_taken_in_something_expensive
# end
- #
- # :api: plugin
- def cleanup_view_runtime
+ def cleanup_view_runtime # :doc:
yield
end
# Every time after an action is processed, this method is invoked
# with the payload, so you can add more information.
- # :api: plugin
- def append_info_to_payload(payload)
+ def append_info_to_payload(payload) # :doc:
payload[:view_runtime] = view_runtime
end
@@ -98,7 +97,6 @@ module ActionController
# A hook which allows other frameworks to log what happened during
# controller process action. This method should return an array
# with the messages to be added.
- # :api: plugin
def log_process_action(payload) #:nodoc:
messages, view_runtime = [], payload[:view_runtime]
messages << ("Views: %.1fms" % view_runtime.to_f) if view_runtime
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index fed99e6c82..2f4c8fb83c 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_dispatch/http/response"
require "delegate"
require "active_support/json"
@@ -239,8 +241,8 @@ module ActionController
error = nil
# This processes the action in a child thread. It lets us return the
- # response code and headers back up the rack stack, and still process
- # the body in parallel with sending data to the client
+ # response code and headers back up the Rack stack, and still process
+ # the body in parallel with sending data to the client.
new_controller_thread {
ActiveSupport::Dependencies.interlock.running do
t2 = Thread.current
@@ -278,9 +280,9 @@ module ActionController
raise error if error
end
- # Spawn a new thread to serve up the controller in. This is to get
+ # Spawn a new thread to serve up the controller in. This is to get
# around the fact that Rack isn't based around IOs and we need to use
- # a thread to stream data from the response bodies. Nobody should call
+ # a thread to stream data from the response bodies. Nobody should call
# this method except in Rails internals. Seriously!
def new_controller_thread # :nodoc:
Thread.new {
@@ -295,7 +297,7 @@ module ActionController
return unless logger
logger.fatal do
- message = "\n#{exception.class} (#{exception.message}):\n"
+ message = "\n#{exception.class} (#{exception.message}):\n".dup
message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
message << " " << exception.backtrace.join("\n ")
"#{message}\n\n"
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index f6aabcb102..2233b93406 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_controller/collector"
module ActionController #:nodoc:
@@ -181,8 +183,8 @@ module ActionController #:nodoc:
#
# request.variant = [:tablet, :phone]
#
- # which will work similarly to formats and MIME types negotiation. If there will be no
- # +:tablet+ variant declared, +:phone+ variant will be picked:
+ # This will work similarly to formats and MIME types negotiation. If there
+ # is no +:tablet+ variant declared, the +:phone+ variant will be used:
#
# respond_to do |format|
# format.html.none
diff --git a/actionpack/lib/action_controller/metal/parameter_encoding.rb b/actionpack/lib/action_controller/metal/parameter_encoding.rb
index 962532ff09..7a45732d31 100644
--- a/actionpack/lib/action_controller/metal/parameter_encoding.rb
+++ b/actionpack/lib/action_controller/metal/parameter_encoding.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# Specify binary encoding for parameters for a given action.
module ParameterEncoding
@@ -39,7 +41,7 @@ module ActionController
# end
#
# The show action in the above controller would have all parameter values
- # encoded as ASCII-8BIT. This is useful in the case where an application
+ # encoded as ASCII-8BIT. This is useful in the case where an application
# must handle data but encoding of the data is unknown, like file system data.
def skip_parameter_encoding(action)
@_parameter_encodings[action.to_s] = true
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 7fc898f034..a678377d4f 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/slice"
require "active_support/core_ext/hash/except"
require "active_support/core_ext/module/anonymous"
@@ -105,7 +107,19 @@ module ActionController
unless super || exclude
if m.respond_to?(:attribute_names) && m.attribute_names.any?
- self.include = m.attribute_names
+ if m.respond_to?(:stored_attributes) && !m.stored_attributes.empty?
+ self.include = m.attribute_names + m.stored_attributes.values.flatten.map(&:to_s)
+ else
+ self.include = m.attribute_names
+ end
+
+ if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
+ self.include += m.nested_attributes_options.keys.map do |key|
+ key.to_s.concat("_attributes")
+ end
+ end
+
+ self.include
end
end
end
@@ -155,8 +169,7 @@ module ActionController
end
included do
- class_attribute :_wrapper_options
- self._wrapper_options = Options.from_hash(format: [])
+ class_attribute :_wrapper_options, default: Options.from_hash(format: [])
end
module ClassMethods
@@ -213,7 +226,7 @@ module ActionController
end
# Sets the default wrapper key or model which will be used to determine
- # wrapper key and attribute names. Will be called automatically when the
+ # wrapper key and attribute names. Called automatically when the
# module is inherited.
def inherited(klass)
if klass._wrapper_options.format.any?
@@ -225,24 +238,19 @@ module ActionController
end
end
- # Performs parameters wrapping upon the request. Will be called automatically
+ # Performs parameters wrapping upon the request. Called automatically
# by the metal call stack.
def process_action(*args)
if _wrapper_enabled?
- if request.parameters[_wrapper_key].present?
- wrapped_hash = _extract_parameters(request.parameters)
- else
- wrapped_hash = _wrap_parameters request.request_parameters
- end
-
+ wrapped_hash = _wrap_parameters request.request_parameters
wrapped_keys = request.request_parameters.keys
wrapped_filtered_hash = _wrap_parameters request.filtered_parameters.slice(*wrapped_keys)
- # This will make the wrapped hash accessible from controller and view
+ # This will make the wrapped hash accessible from controller and view.
request.parameters.merge! wrapped_hash
request.request_parameters.merge! wrapped_hash
- # This will display the wrapped hash in the log file
+ # This will display the wrapped hash in the log file.
request.filtered_parameters.merge! wrapped_filtered_hash
end
super
@@ -279,7 +287,7 @@ module ActionController
return false unless request.has_content_type?
ref = request.content_mime_type.ref
- _wrapper_formats.include?(ref) && _wrapper_key && !request.request_parameters[_wrapper_key]
+ _wrapper_formats.include?(ref) && _wrapper_key && !request.parameters.key?(_wrapper_key)
end
end
end
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 1836a07d4e..4c2b5120eb 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Redirecting
extend ActiveSupport::Concern
@@ -22,21 +24,21 @@ module ActionController
# redirect_to posts_url
# redirect_to proc { edit_post_url(@post) }
#
- # The redirection happens as a "302 Found" header unless otherwise specified using the <tt>:status</tt> option:
+ # The redirection happens as a <tt>302 Found</tt> header unless otherwise specified using the <tt>:status</tt> option:
#
# redirect_to post_url(@post), status: :found
# redirect_to action: 'atom', status: :moved_permanently
# redirect_to post_url(@post), status: 301
# redirect_to action: 'atom', status: 302
#
- # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
+ # The status code can either be a standard {HTTP Status code}[https://www.iana.org/assignments/http-status-codes] as an
# integer, or a symbol representing the downcased, underscored and symbolized description.
# Note that the status code must be a 3xx HTTP code, or redirection will not occur.
#
# If you are using XHR requests other than GET or POST and redirecting after the
# request then some browsers will follow the redirect using the original request
# method. This may lead to undesirable behavior such as a double DELETE. To work
- # around this you can return a <tt>303 See Other</tt> status code which will be
+ # around this you can return a <tt>303 See Other</tt> status code which will be
# followed using a GET request.
#
# redirect_to posts_url, status: :see_other
@@ -66,7 +68,7 @@ module ActionController
# if possible, otherwise redirects to the provided default fallback
# location.
#
- # The referrer information is pulled from the HTTP `Referer` (sic) header on
+ # The referrer information is pulled from the HTTP +Referer+ (sic) header on
# the request. This is an optional header and its presence on the request is
# subject to browser security settings and user preferences. If the request
# is missing this header, the <tt>fallback_location</tt> will be used.
@@ -77,15 +79,18 @@ module ActionController
# redirect_back fallback_location: "/images/screenshot.jpg"
# redirect_back fallback_location: posts_url
# redirect_back fallback_location: proc { edit_post_url(@post) }
+ # redirect_back fallback_location: '/', allow_other_host: false
+ #
+ # ==== Options
+ # * <tt>:fallback_location</tt> - The default fallback location that will be used on missing +Referer+ header.
+ # * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
#
- # All options that can be passed to <tt>redirect_to</tt> are accepted as
+ # All other options that can be passed to <tt>redirect_to</tt> are accepted as
# options and the behavior is identical.
- def redirect_back(fallback_location:, **args)
- if referer = request.headers["Referer"]
- redirect_to referer, **args
- else
- redirect_to fallback_location, **args
- end
+ def redirect_back(fallback_location:, allow_other_host: true, **args)
+ referer = request.headers["Referer"]
+ redirect_to_referer = referer && (allow_other_host || _url_host_allowed?(referer))
+ redirect_to redirect_to_referer ? referer : fallback_location, **args
end
def _compute_redirect_to_location(request, options) #:nodoc:
@@ -93,7 +98,7 @@ module ActionController
# The scheme name consist of a letter followed by any combination of
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
# characters; and is terminated by a colon (":").
- # See http://tools.ietf.org/html/rfc3986#section-3.1
+ # See https://tools.ietf.org/html/rfc3986#section-3.1
# The protocol relative scheme starts with a double slash "//".
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i
options
@@ -118,5 +123,11 @@ module ActionController
302
end
end
+
+ def _url_host_allowed?(url)
+ URI(url.to_s).host == request.host
+ rescue ArgumentError, URI::Error
+ false
+ end
end
end
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 733aca195d..b81d3ef539 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "set"
module ActionController
@@ -26,8 +28,7 @@ module ActionController
RENDERERS = Set.new
included do
- class_attribute :_renderers
- self._renderers = Set.new.freeze
+ class_attribute :_renderers, default: Set.new.freeze
end
# Used in <tt>ActionController::Base</tt>
@@ -84,7 +85,7 @@ module ActionController
def self.remove(key)
RENDERERS.delete(key.to_sym)
method_name = _render_with_renderer_method_name(key)
- remove_method(method_name) if method_defined?(method_name)
+ remove_possible_method(method_name)
end
def self._render_with_renderer_method_name(key)
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 6b17719381..6d181e6456 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -1,4 +1,4 @@
-require "active_support/core_ext/string/filters"
+# frozen_string_literal: true
module ActionController
module Rendering
@@ -36,11 +36,11 @@ module ActionController
super
end
- # Overwrite render_to_string because body can now be set to a rack body.
+ # Overwrite render_to_string because body can now be set to a Rack body.
def render_to_string(*)
result = super
if result.respond_to?(:each)
- string = ""
+ string = "".dup
result.each { |r| string << r }
string
else
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index e8965a6561..0ab313e398 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -1,6 +1,9 @@
+# frozen_string_literal: true
+
require "rack/session/abstract/id"
require "action_controller/metal/exceptions"
require "active_support/security_utils"
+require "active_support/core_ext/string/strip"
module ActionController #:nodoc:
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
@@ -20,7 +23,7 @@ module ActionController #:nodoc:
# Since HTML and JavaScript requests are typically made from the browser, we
# need to ensure to verify request authenticity for the web browser. We can
# use session-oriented authentication for these types of requests, by using
- # the `protect_from_forgery` method in our controllers.
+ # the <tt>protect_from_forgery</tt> method in our controllers.
#
# GET requests are not protected since they don't have side effects like writing
# to the database and don't leak sensitive information. JavaScript requests are
@@ -85,6 +88,10 @@ module ActionController #:nodoc:
config_accessor :per_form_csrf_tokens
self.per_form_csrf_tokens = false
+ # Controls whether forgery protection is enabled by default.
+ config_accessor :default_protect_from_forgery
+ self.default_protect_from_forgery = false
+
helper_method :form_authenticity_token
helper_method :protect_against_forgery?
end
@@ -128,6 +135,15 @@ module ActionController #:nodoc:
append_after_action :verify_same_origin_request
end
+ # Turn off request forgery protection. This is a wrapper for:
+ #
+ # skip_before_action :verify_authenticity_token
+ #
+ # See +skip_before_action+ for allowed options.
+ def skip_forgery_protection(options = {})
+ skip_before_action :verify_authenticity_token, options
+ end
+
private
def protection_method_class(name)
@@ -201,7 +217,7 @@ module ActionController #:nodoc:
# The actual before_action that is used to verify the CSRF token.
# Don't override this directly. Provide your own forgery protection
# strategy instead. If you override, you'll disable same-origin
- # `<script>` verification.
+ # <tt><script></tt> verification.
#
# Lean on the protect_from_forgery declaration to mark which actions are
# due for same-origin request verification. If protect_from_forgery is
@@ -213,7 +229,11 @@ module ActionController #:nodoc:
if !verified_request?
if logger && log_warning_on_csrf_failure
- logger.warn "Can't verify CSRF token authenticity."
+ if valid_request_origin?
+ logger.warn "Can't verify CSRF token authenticity."
+ else
+ logger.warn "HTTP Origin header (#{request.origin}) didn't match request.base_url (#{request.base_url})"
+ end
end
handle_unverified_request
end
@@ -229,8 +249,9 @@ module ActionController #:nodoc:
"If you know what you're doing, go ahead and disable forgery " \
"protection on this action to permit cross-origin JavaScript embedding."
private_constant :CROSS_ORIGIN_JAVASCRIPT_WARNING
+ # :startdoc:
- # If `verify_authenticity_token` was run (indicating that we have
+ # If +verify_authenticity_token+ was run (indicating that we have
# forgery protection enabled for this request) then also verify that
# we aren't serving an unauthorized cross-origin response.
def verify_same_origin_request # :doc:
@@ -247,7 +268,7 @@ module ActionController #:nodoc:
@marked_for_same_origin_verification = request.get?
end
- # If the `verify_authenticity_token` before_action ran, verify that
+ # If the +verify_authenticity_token+ before_action ran, verify that
# JavaScript responses are only served to same-origin GET requests.
def marked_for_same_origin_verification? # :doc:
@marked_for_same_origin_verification ||= false
@@ -262,9 +283,9 @@ module ActionController #:nodoc:
# Returns true or false if a request is verified. Checks:
#
- # * Is it a GET or HEAD request? Gets should be safe and idempotent
+ # * Is it a GET or HEAD request? GETs should be safe and idempotent
# * Does the form_authenticity_token match the given token value from the params?
- # * Does the X-CSRF-Token header match the form_authenticity_token
+ # * Does the X-CSRF-Token header match the form_authenticity_token?
def verified_request? # :doc:
!protect_against_forgery? || request.get? || request.head? ||
(valid_request_origin? && any_authenticity_token_valid?)
@@ -327,7 +348,7 @@ module ActionController #:nodoc:
if masked_token.length == AUTHENTICITY_TOKEN_LENGTH
# This is actually an unmasked token. This is expected if
# you have just upgraded to masked tokens, but should stop
- # happening shortly after installing this gem
+ # happening shortly after installing this gem.
compare_with_real_token masked_token, session
elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
@@ -336,20 +357,20 @@ module ActionController #:nodoc:
compare_with_real_token(csrf_token, session) ||
valid_per_form_csrf_token?(csrf_token, session)
else
- false # Token is malformed
+ false # Token is malformed.
end
end
def unmask_token(masked_token) # :doc:
# Split the token into the one-time pad and the encrypted
- # value and decrypt it
+ # value and decrypt it.
one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
encrypted_csrf_token = masked_token[AUTHENTICITY_TOKEN_LENGTH..-1]
xor_byte_strings(one_time_pad, encrypted_csrf_token)
end
def compare_with_real_token(token, session) # :doc:
- ActiveSupport::SecurityUtils.secure_compare(token, real_csrf_token(session))
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
end
def valid_per_form_csrf_token?(token, session) # :doc:
@@ -360,7 +381,7 @@ module ActionController #:nodoc:
request.request_method
)
- ActiveSupport::SecurityUtils.secure_compare(token, correct_token)
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, correct_token)
else
false
end
@@ -395,11 +416,21 @@ module ActionController #:nodoc:
allow_forgery_protection
end
+ NULL_ORIGIN_MESSAGE = <<-MSG.strip_heredoc
+ The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
+ means you have the 'no-referrer' Referrer-Policy header enabled, or that you the request came from a site that
+ refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
+ best solution is to change your referrer policy to something less strict like same-origin or strict-same-origin.
+ If you cannot change the referrer policy, you can disable origin checking with the
+ Rails.application.config.action_controller.forgery_protection_origin_check setting.
+ MSG
+
# Checks if the request originated from the same origin by looking at the
# Origin header.
def valid_request_origin? # :doc:
if forgery_protection_origin_check
# We accept blank origin headers because some user agents don't send it.
+ raise InvalidAuthenticityToken, NULL_ORIGIN_MESSAGE if request.origin == "null"
request.origin.nil? || request.origin == request.base_url
else
true
diff --git a/actionpack/lib/action_controller/metal/rescue.rb b/actionpack/lib/action_controller/metal/rescue.rb
index 2d99e4045b..44f7fb7a07 100644
--- a/actionpack/lib/action_controller/metal/rescue.rb
+++ b/actionpack/lib/action_controller/metal/rescue.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
module ActionController #:nodoc:
- # This module is responsible for providing `rescue_from` helpers
+ # This module is responsible for providing +rescue_from+ helpers
# to controllers and configuring when detailed exceptions must be
# shown.
module Rescue
@@ -8,9 +10,9 @@ module ActionController #:nodoc:
# Override this method if you want to customize when detailed
# exceptions must be shown. This method is only called when
- # consider_all_requests_local is false. By default, it returns
- # false, but someone may set it to `request.local?` so local
- # requests in production still shows the detailed exception pages.
+ # +consider_all_requests_local+ is +false+. By default, it returns
+ # +false+, but someone may set it to <tt>request.local?</tt> so local
+ # requests in production still show the detailed exception pages.
def show_detailed_exceptions?
false
end
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 877a08b222..8dc01a5eb9 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
require "rack/chunked"
module ActionController #:nodoc:
# Allows views to be streamed back to the client as they are rendered.
#
- # The default way Rails renders views is by first rendering the template
+ # By default, Rails renders views by first rendering the template
# and then the layout. The response is sent to the client after the whole
# template is rendered, all queries are made, and the layout is processed.
#
@@ -181,7 +183,7 @@ module ActionController #:nodoc:
# unicorn_rails --config-file unicorn.config.rb
#
# You may also want to configure other parameters like <tt>:tcp_nodelay</tt>.
- # Please check its documentation for more information: http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-listen
+ # Please check its documentation for more information: https://bogomips.org/unicorn/Unicorn/Configurator.html#method-i-listen
#
# If you are using Unicorn with NGINX, you may need to tweak NGINX.
# Streaming should work out of the box on Rainbows.
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 3b293baa73..a56ac749f8 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/indifferent_access"
require "active_support/core_ext/hash/transform_values"
require "active_support/core_ext/array/wrap"
@@ -43,6 +45,18 @@ module ActionController
end
end
+ # Raised when a Parameters instance is not marked as permitted and
+ # an operation to transform it to hash is called.
+ #
+ # params = ActionController::Parameters.new(a: "123", b: "456")
+ # params.to_h
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+ class UnfilteredParameters < ArgumentError
+ def initialize # :nodoc:
+ super("unable to convert unpermitted parameters to hash")
+ end
+ end
+
# == Action Controller \Parameters
#
# Allows you to choose which attributes should be whitelisted for mass updating
@@ -53,9 +67,9 @@ module ActionController
#
# params = ActionController::Parameters.new({
# person: {
- # name: 'Francesco',
+ # name: "Francesco",
# age: 22,
- # role: 'admin'
+ # role: "admin"
# }
# })
#
@@ -103,17 +117,95 @@ module ActionController
# You can fetch values of <tt>ActionController::Parameters</tt> using either
# <tt>:key</tt> or <tt>"key"</tt>.
#
- # params = ActionController::Parameters.new(key: 'value')
+ # params = ActionController::Parameters.new(key: "value")
# params[:key] # => "value"
# params["key"] # => "value"
class Parameters
- cattr_accessor :permit_all_parameters, instance_accessor: false
- self.permit_all_parameters = false
+ cattr_accessor :permit_all_parameters, instance_accessor: false, default: false
cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
+ ##
+ # :method: as_json
+ #
+ # :call-seq:
+ # as_json(options=nil)
+ #
+ # Returns a hash that can be used as the JSON representation for the parameters.
+
+ ##
+ # :method: empty?
+ #
+ # :call-seq:
+ # empty?()
+ #
+ # Returns true if the parameters have no key/value pairs.
+
+ ##
+ # :method: has_key?
+ #
+ # :call-seq:
+ # has_key?(key)
+ #
+ # Returns true if the given key is present in the parameters.
+
+ ##
+ # :method: has_value?
+ #
+ # :call-seq:
+ # has_value?(value)
+ #
+ # Returns true if the given value is present for some key in the parameters.
+
+ ##
+ # :method: include?
+ #
+ # :call-seq:
+ # include?(key)
+ #
+ # Returns true if the given key is present in the parameters.
+
+ ##
+ # :method: key?
+ #
+ # :call-seq:
+ # key?(key)
+ #
+ # Returns true if the given key is present in the parameters.
+
+ ##
+ # :method: keys
+ #
+ # :call-seq:
+ # keys()
+ #
+ # Returns a new array of the keys of the parameters.
+
+ ##
+ # :method: to_s
+ #
+ # :call-seq:
+ # to_s()
+ #
+ # Returns the content of the parameters as a string.
+
+ ##
+ # :method: value?
+ #
+ # :call-seq:
+ # value?(value)
+ #
+ # Returns true if the given value is present for some key in the parameters.
+
+ ##
+ # :method: values
+ #
+ # :call-seq:
+ # values()
+ #
+ # Returns a new array of the values of the parameters.
delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?,
- :as_json, to: :@parameters
+ :as_json, :to_s, to: :@parameters
# By default, never raise an UnpermittedParameters exception if these
# params are present. The default includes both 'controller' and 'action'
@@ -122,8 +214,7 @@ module ActionController
# config. For instance:
#
# config.always_permitted_parameters = %w( controller action format )
- cattr_accessor :always_permitted_parameters
- self.always_permitted_parameters = %w( controller action )
+ cattr_accessor :always_permitted_parameters, default: %w( controller action )
# Returns a new instance of <tt>ActionController::Parameters</tt>.
# Also, sets the +permitted+ attribute to the default value of
@@ -132,13 +223,13 @@ module ActionController
# class Person < ActiveRecord::Base
# end
#
- # params = ActionController::Parameters.new(name: 'Francesco')
+ # params = ActionController::Parameters.new(name: "Francesco")
# params.permitted? # => false
# Person.new(params) # => ActiveModel::ForbiddenAttributesError
#
# ActionController::Parameters.permit_all_parameters = true
#
- # params = ActionController::Parameters.new(name: 'Francesco')
+ # params = ActionController::Parameters.new(name: "Francesco")
# params.permitted? # => true
# Person.new(params) # => #<Person id: nil, name: "Francesco">
def initialize(parameters = {})
@@ -157,13 +248,14 @@ module ActionController
end
# Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
- # representation of this parameter with all unpermitted keys removed.
+ # representation of the parameters with all unpermitted keys removed.
#
# params = ActionController::Parameters.new({
- # name: 'Senjougahara Hitagi',
- # oddity: 'Heavy stone crab'
+ # name: "Senjougahara Hitagi",
+ # oddity: "Heavy stone crab"
# })
- # params.to_h # => {}
+ # params.to_h
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
#
# safe_params = params.permit(:name)
# safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
@@ -171,17 +263,66 @@ module ActionController
if permitted?
convert_parameters_to_hashes(@parameters, :to_h)
else
- slice(*self.class.always_permitted_parameters).permit!.to_h
+ raise UnfilteredParameters
end
end
+ # Returns a safe <tt>Hash</tt> representation of the parameters
+ # with all unpermitted keys removed.
+ #
+ # params = ActionController::Parameters.new({
+ # name: "Senjougahara Hitagi",
+ # oddity: "Heavy stone crab"
+ # })
+ # params.to_hash
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+ #
+ # safe_params = params.permit(:name)
+ # safe_params.to_hash # => {"name"=>"Senjougahara Hitagi"}
+ def to_hash
+ to_h.to_hash
+ end
+
+ # Returns a string representation of the receiver suitable for use as a URL
+ # query string:
+ #
+ # params = ActionController::Parameters.new({
+ # name: "David",
+ # nationality: "Danish"
+ # })
+ # params.to_query
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+ #
+ # safe_params = params.permit(:name, :nationality)
+ # safe_params.to_query
+ # # => "name=David&nationality=Danish"
+ #
+ # An optional namespace can be passed to enclose key names:
+ #
+ # params = ActionController::Parameters.new({
+ # name: "David",
+ # nationality: "Danish"
+ # })
+ # safe_params = params.permit(:name, :nationality)
+ # safe_params.to_query("user")
+ # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
+ #
+ # The string pairs "key=value" that conform the query string
+ # are sorted lexicographically in ascending order.
+ #
+ # This method is also aliased as +to_param+.
+ def to_query(*args)
+ to_h.to_query(*args)
+ end
+ alias_method :to_param, :to_query
+
# Returns an unsafe, unfiltered
- # <tt>ActiveSupport::HashWithIndifferentAccess</tt> representation of this
- # parameter.
+ # <tt>ActiveSupport::HashWithIndifferentAccess</tt> representation of the
+ # parameters.
#
# params = ActionController::Parameters.new({
- # name: 'Senjougahara Hitagi',
- # oddity: 'Heavy stone crab'
+ # name: "Senjougahara Hitagi",
+ # oddity: "Heavy stone crab"
# })
# params.to_unsafe_h
# # => {"name"=>"Senjougahara Hitagi", "oddity" => "Heavy stone crab"}
@@ -191,10 +332,10 @@ module ActionController
alias_method :to_unsafe_hash, :to_unsafe_h
# Convert all hashes in values into parameters, then yield each pair in
- # the same way as <tt>Hash#each_pair</tt>
+ # the same way as <tt>Hash#each_pair</tt>.
def each_pair(&block)
@parameters.each_pair do |key, value|
- yield key, convert_hashes_to_parameters(key, value)
+ yield [key, convert_hashes_to_parameters(key, value)]
end
end
alias_method :each, :each_pair
@@ -226,7 +367,7 @@ module ActionController
# class Person < ActiveRecord::Base
# end
#
- # params = ActionController::Parameters.new(name: 'Francesco')
+ # params = ActionController::Parameters.new(name: "Francesco")
# params.permitted? # => false
# Person.new(params) # => ActiveModel::ForbiddenAttributesError
# params.permit!
@@ -248,7 +389,7 @@ module ActionController
# When passed a single key, if it exists and its associated value is
# either present or the singleton +false+, returns said value:
#
- # ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
+ # ActionController::Parameters.new(person: { name: "Francesco" }).require(:person)
# # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
#
# Otherwise raises <tt>ActionController::ParameterMissing</tt>:
@@ -281,7 +422,7 @@ module ActionController
# Technically this method can be used to fetch terminal values:
#
# # CAREFUL
- # params = ActionController::Parameters.new(person: { name: 'Finn' })
+ # params = ActionController::Parameters.new(person: { name: "Finn" })
# name = params.require(:person).require(:name) # CAREFUL
#
# but take into account that at some point those ones have to be permitted:
@@ -311,7 +452,7 @@ module ActionController
# for the object to +true+. This is useful for limiting which attributes
# should be allowed for mass updating.
#
- # params = ActionController::Parameters.new(user: { name: 'Francesco', age: 22, role: 'admin' })
+ # params = ActionController::Parameters.new(user: { name: "Francesco", age: 22, role: "admin" })
# permitted = params.require(:user).permit(:name, :age)
# permitted.permitted? # => true
# permitted.has_key?(:name) # => true
@@ -331,7 +472,7 @@ module ActionController
# You may declare that the parameter should be an array of permitted scalars
# by mapping it to an empty array:
#
- # params = ActionController::Parameters.new(tags: ['rails', 'parameters'])
+ # params = ActionController::Parameters.new(tags: ["rails", "parameters"])
# params.permit(tags: [])
#
# Sometimes it is not possible or convenient to declare the valid keys of
@@ -339,7 +480,7 @@ module ActionController
#
# params.permit(preferences: {})
#
- # but be careful because this opens the door to arbitrary input. In this
+ # Be careful because this opens the door to arbitrary input. In this
# case, +permit+ ensures values in the returned structure are permitted
# scalars and filters out anything else.
#
@@ -347,11 +488,11 @@ module ActionController
#
# params = ActionController::Parameters.new({
# person: {
- # name: 'Francesco',
+ # name: "Francesco",
# age: 22,
# pets: [{
- # name: 'Purplish',
- # category: 'dogs'
+ # name: "Purplish",
+ # category: "dogs"
# }]
# }
# })
@@ -370,8 +511,8 @@ module ActionController
# params = ActionController::Parameters.new({
# person: {
# contact: {
- # email: 'none@test.com',
- # phone: '555-1234'
+ # email: "none@test.com",
+ # phone: "555-1234"
# }
# }
# })
@@ -404,7 +545,7 @@ module ActionController
# Returns a parameter for the given +key+. If not found,
# returns +nil+.
#
- # params = ActionController::Parameters.new(person: { name: 'Francesco' })
+ # params = ActionController::Parameters.new(person: { name: "Francesco" })
# params[:person] # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
# params[:none] # => nil
def [](key)
@@ -423,11 +564,11 @@ module ActionController
# if more arguments are given, then that will be returned; if a block
# is given, then that will be run and its result returned.
#
- # params = ActionController::Parameters.new(person: { name: 'Francesco' })
+ # params = ActionController::Parameters.new(person: { name: "Francesco" })
# params.fetch(:person) # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
# params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none
- # params.fetch(:none, 'Francesco') # => "Francesco"
- # params.fetch(:none) { 'Francesco' } # => "Francesco"
+ # params.fetch(:none, "Francesco") # => "Francesco"
+ # params.fetch(:none) { "Francesco" } # => "Francesco"
def fetch(key, *args)
convert_value_to_parameters(
@parameters.fetch(key) {
@@ -534,12 +675,12 @@ module ActionController
self
end
- # Deletes and returns a key-value pair from +Parameters+ whose key is equal
- # to key. If the key is not found, returns the default value. If the
- # optional code block is given and the key is not found, pass in the key
- # and return the result of block.
- def delete(key)
- convert_value_to_parameters(@parameters.delete(key))
+ # Deletes a key-value pair from +Parameters+ and returns the value. If
+ # +key+ is not found, returns +nil+ (or, with optional code block, yields
+ # +key+ and returns the result). Cf. +#extract!+, which returns the
+ # corresponding +ActionController::Parameters+ object.
+ def delete(key, &block)
+ convert_value_to_parameters(@parameters.delete(key, &block))
end
# Returns a new instance of <tt>ActionController::Parameters</tt> with only
@@ -575,20 +716,37 @@ module ActionController
end
# Returns a new <tt>ActionController::Parameters</tt> with all keys from
- # +other_hash+ merges into current hash.
+ # +other_hash+ merged into current hash.
def merge(other_hash)
new_instance_with_inherited_permitted_status(
@parameters.merge(other_hash.to_h)
)
end
- # Returns current <tt>ActionController::Parameters</tt> instance which
- # +other_hash+ merges into current hash.
+ # Returns current <tt>ActionController::Parameters</tt> instance with
+ # +other_hash+ merged into current hash.
def merge!(other_hash)
@parameters.merge!(other_hash.to_h)
self
end
+ # Returns a new <tt>ActionController::Parameters</tt> with all keys from
+ # current hash merged into +other_hash+.
+ def reverse_merge(other_hash)
+ new_instance_with_inherited_permitted_status(
+ other_hash.to_h.merge(@parameters)
+ )
+ end
+ alias_method :with_defaults, :reverse_merge
+
+ # Returns current <tt>ActionController::Parameters</tt> instance with
+ # current hash merged into +other_hash+.
+ def reverse_merge!(other_hash)
+ @parameters.merge!(other_hash.to_h) { |key, left, right| left }
+ self
+ end
+ alias_method :with_defaults!, :reverse_merge!
+
# This is required by ActiveModel attribute assignment, so that user can
# pass +Parameters+ to a mass assignment methods in a model. It should not
# matter as we are using +HashWithIndifferentAccess+ internally.
@@ -627,9 +785,7 @@ module ActionController
end
end
- undef_method :to_param
-
- # Returns duplicate of object including all parameters
+ # Returns duplicate of object including all parameters.
def deep_dup
self.class.new(@parameters.deep_dup).tap do |duplicate|
duplicate.permitted = @permitted
@@ -849,7 +1005,7 @@ module ActionController
# whitelisted.
#
# In addition, parameters can be marked as required and flow through a
- # predefined raise/rescue flow to end up as a 400 Bad Request with no
+ # predefined raise/rescue flow to end up as a <tt>400 Bad Request</tt> with no
# effort.
#
# class PeopleController < ActionController::Base
@@ -873,7 +1029,7 @@ module ActionController
#
# private
# # Using a private method to encapsulate the permissible parameters is
- # # just a good pattern since you'll be able to reuse the same permit
+ # # a good pattern since you'll be able to reuse the same permit
# # list between create and update. Also, you can specialize this method
# # with per-user checking of permissible attributes.
# def person_params
diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb
index 9bb416178a..6e8a95040f 100644
--- a/actionpack/lib/action_controller/metal/testing.rb
+++ b/actionpack/lib/action_controller/metal/testing.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Testing
extend ActiveSupport::Concern
@@ -10,11 +12,5 @@ module ActionController
self.params = nil
end
end
-
- module ClassMethods
- def before_filters
- _process_action_callbacks.find_all { |x| x.kind == :before }.map(&:name)
- end
- end
end
end
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 9f3cc099d6..84dbb59a63 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module ActionController
# Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing
# the <tt>_routes</tt> method. Otherwise, an exception will be raised.
#
# In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
- # url options like the +host+. In order to do so, this module requires the host class
+ # URL options like the +host+. In order to do so, this module requires the host class
# to implement +env+ which needs to be Rack-compatible and +request+
# which is either an instance of +ActionDispatch::Request+ or an object
# that responds to the +host+, +optional_port+, +protocol+ and
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index a7cdfe6a98..7d42f5d931 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails"
require "action_controller"
require "action_dispatch/railtie"
@@ -22,13 +24,15 @@ module ActionController
initializer "action_controller.parameters_config" do |app|
options = app.config.action_controller
- ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
- if app.config.action_controller[:always_permitted_parameters]
- ActionController::Parameters.always_permitted_parameters =
- app.config.action_controller.delete(:always_permitted_parameters)
- end
- ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
- (Rails.env.test? || Rails.env.development?) ? :log : false
+ ActiveSupport.on_load(:action_controller, run_once: true) do
+ ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
+ if app.config.action_controller[:always_permitted_parameters]
+ ActionController::Parameters.always_permitted_parameters =
+ app.config.action_controller.delete(:always_permitted_parameters)
+ end
+ ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
+ (Rails.env.test? || Rails.env.development?) ? :log : false
+ end
end
end
@@ -42,7 +46,7 @@ module ActionController
options.javascripts_dir ||= paths["public/javascripts"].first
options.stylesheets_dir ||= paths["public/stylesheets"].first
- # Ensure readers methods get compiled
+ # Ensure readers methods get compiled.
options.asset_host ||= app.config.asset_host
options.relative_url_root ||= app.config.relative_url_root
@@ -67,5 +71,19 @@ module ActionController
config.compile_methods! if config.respond_to?(:compile_methods!)
end
end
+
+ initializer "action_controller.request_forgery_protection" do |app|
+ ActiveSupport.on_load(:action_controller_base) do
+ if app.config.action_controller.default_protect_from_forgery
+ protect_from_forgery with: :exception
+ end
+ end
+ end
+
+ initializer "action_controller.eager_load_actions" do
+ ActiveSupport.on_load(:after_initialize) do
+ ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
+ end
+ end
end
end
diff --git a/actionpack/lib/action_controller/railties/helpers.rb b/actionpack/lib/action_controller/railties/helpers.rb
index 3985c6b273..fa746fa9e8 100644
--- a/actionpack/lib/action_controller/railties/helpers.rb
+++ b/actionpack/lib/action_controller/railties/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Railties
module Helpers
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index e1441bd343..49c5b782f0 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/keys"
module ActionController
@@ -5,7 +7,7 @@ module ActionController
# without requirement of being in controller actions.
#
# You get a concrete renderer class by invoking ActionController::Base#renderer.
- # For example,
+ # For example:
#
# ApplicationController.renderer
#
@@ -18,7 +20,7 @@ module ActionController
# ApplicationController.render template: '...'
#
# #render allows you to use the same options that you can use when rendering in a controller.
- # For example,
+ # For example:
#
# FooController.render :action, locals: { ... }, assigns: { ... }
#
@@ -56,7 +58,7 @@ module ActionController
# Create a new renderer for the same controller but with new defaults.
def with_defaults(defaults)
- self.class.new controller, env, self.defaults.merge(defaults)
+ self.class.new controller, @env, self.defaults.merge(defaults)
end
# Accepts a custom Rack environment to render templates in.
diff --git a/actionpack/lib/action_controller/template_assertions.rb b/actionpack/lib/action_controller/template_assertions.rb
index 0179f4afcd..dd83c1a283 100644
--- a/actionpack/lib/action_controller/template_assertions.rb
+++ b/actionpack/lib/action_controller/template_assertions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module TemplateAssertions
def assert_template(options = {}, message = nil)
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 7229c67f30..4b408750a4 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
require "rack/session/abstract/id"
require "active_support/core_ext/hash/conversions"
require "active_support/core_ext/object/to_query"
require "active_support/core_ext/module/anonymous"
+require "active_support/core_ext/module/redefine_method"
require "active_support/core_ext/hash/keys"
require "active_support/testing/constant_lookup"
require "action_controller/template_assertions"
@@ -13,11 +16,11 @@ module ActionController
end
module Live
- # Disable controller / rendering threads in tests. User tests can access
+ # Disable controller / rendering threads in tests. User tests can access
# the database on the main thread, so they could open a txn, then the
# controller thread will open a new connection and try to access data
- # that's only visible to the main thread's txn. This is the problem in #23483
- remove_method :new_controller_thread
+ # that's only visible to the main thread's txn. This is the problem in #23483.
+ silence_redefinition_of_method :new_controller_thread
def new_controller_thread # :nodoc:
yield
end
@@ -35,7 +38,7 @@ module ActionController
attr_reader :controller_class
- # Create a new test request with default `env` values
+ # Create a new test request with default `env` values.
def self.create(controller_class)
env = {}
env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
@@ -131,7 +134,7 @@ module ActionController
include Rack::Test::Utils
def should_multipart?(params)
- # FIXME: lifted from Rack-Test. We should push this separation upstream
+ # FIXME: lifted from Rack-Test. We should push this separation upstream.
multipart = false
query = lambda { |value|
case value
@@ -300,7 +303,7 @@ module ActionController
# assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
# assert flash.empty? # makes sure that there's nothing in the flash
#
- # On top of the collections, you have the complete url that a given action redirected to available in <tt>redirect_to_url</tt>.
+ # On top of the collections, you have the complete URL that a given action redirected to available in <tt>redirect_to_url</tt>.
#
# For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
# action call which can then be asserted against.
@@ -534,7 +537,6 @@ module ActionController
@request.delete_header "HTTP_ACCEPT"
end
@request.query_string = ""
- @request.env.delete "PATH_INFO"
@response.sent!
end