aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xactionmailer/bin/test4
-rwxr-xr-xactionpack/bin/test4
-rw-r--r--actionpack/lib/action_controller.rb1
-rw-r--r--actionpack/lib/action_controller/base.rb2
-rw-r--r--actionpack/lib/action_controller/metal.rb4
-rw-r--r--actionpack/lib/action_controller/metal/parameter_encoding.rb30
-rw-r--r--actionpack/lib/action_controller/test_case.rb18
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb16
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb1
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb2
-rw-r--r--actionpack/test/abstract/translation_test.rb3
-rw-r--r--actionpack/test/abstract_unit.rb18
-rw-r--r--actionpack/test/controller/new_base/render_action_test.rb3
-rw-r--r--actionpack/test/controller/parameter_encoding_test.rb73
-rw-r--r--actionpack/test/controller/parameters/always_permitted_parameters_test.rb3
-rw-r--r--actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb12
-rw-r--r--actionpack/test/controller/parameters/multi_parameter_attributes_test.rb3
-rw-r--r--actionpack/test/controller/parameters/nested_parameters_permit_test.rb30
-rw-r--r--actionpack/test/controller/parameters/raise_on_unpermitted_params_test.rb6
-rw-r--r--actionpack/test/controller/routing_test.rb9
-rw-r--r--actionpack/test/journey/route_test.rb6
-rwxr-xr-xactionview/bin/test4
-rw-r--r--actionview/lib/action_view/helpers/tag_helper.rb4
-rw-r--r--actionview/lib/action_view/test_case.rb2
-rw-r--r--actionview/test/actionpack/controller/view_paths_test.rb6
-rw-r--r--actionview/test/template/form_helper_test.rb9
-rw-r--r--actionview/test/template/tag_helper_test.rb18
-rwxr-xr-xactivemodel/bin/test4
-rw-r--r--activemodel/lib/active_model/errors.rb3
-rw-r--r--activemodel/test/cases/validations/confirmation_validation_test.rb3
-rwxr-xr-xactiverecord/bin/test4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/active_schema_test.rb6
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb3
-rw-r--r--activerecord/test/cases/base_test.rb3
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb3
-rw-r--r--activerecord/test/cases/persistence_test.rb3
-rw-r--r--activerecord/test/cases/scoping/relation_scoping_test.rb2
-rw-r--r--activerecord/test/cases/validations_test.rb6
-rwxr-xr-xactivesupport/bin/test4
-rw-r--r--guides/rails_guides/markdown.rb3
-rw-r--r--guides/source/action_cable_overview.md6
-rw-r--r--guides/source/active_model_basics.md7
-rw-r--r--guides/source/active_record_querying.md5
-rw-r--r--guides/source/caching_with_rails.md24
-rw-r--r--guides/source/debugging_rails_applications.md1
-rw-r--r--railties/lib/rails/commands/server.rb3
-rw-r--r--railties/lib/rails/engine/commands_tasks.rb2
-rw-r--r--railties/test/engine/commands_tasks_test.rb24
-rw-r--r--railties/test/json_params_parsing_test.rb47
52 files changed, 378 insertions, 89 deletions
diff --git a/actionmailer/bin/test b/actionmailer/bin/test
index 404cabba51..84a05bba08 100755
--- a/actionmailer/bin/test
+++ b/actionmailer/bin/test
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
-COMPONENT_ROOT = File.expand_path("../../", __FILE__)
+
+COMPONENT_ROOT = File.expand_path("..", __dir__)
require File.expand_path("../tools/test", COMPONENT_ROOT)
+
exit Minitest.run(ARGV)
diff --git a/actionpack/bin/test b/actionpack/bin/test
index 404cabba51..84a05bba08 100755
--- a/actionpack/bin/test
+++ b/actionpack/bin/test
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
-COMPONENT_ROOT = File.expand_path("../../", __FILE__)
+
+COMPONENT_ROOT = File.expand_path("..", __dir__)
require File.expand_path("../tools/test", COMPONENT_ROOT)
+
exit Minitest.run(ARGV)
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index b9ef11a7e0..fc86a907b3 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -40,6 +40,7 @@ module ActionController
autoload :Rescue
autoload :Streaming
autoload :StrongParameters
+ autoload :ParameterEncoding
autoload :Testing
autoload :UrlFor
end
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 2c7a223971..68a526eccb 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -217,7 +217,7 @@ module ActionController
MimeResponds,
ImplicitRender,
StrongParameters,
-
+ ParameterEncoding,
Cookies,
Flash,
FormBuilder,
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 0364500944..075e4504c2 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -139,6 +139,10 @@ module ActionController
end
end
+ def self.encoding_for_param(action, param) # :nodoc:
+ ::Encoding::UTF_8
+ end
+
# Delegates to the class' <tt>controller_name</tt>
def controller_name
self.class.controller_name
diff --git a/actionpack/lib/action_controller/metal/parameter_encoding.rb b/actionpack/lib/action_controller/metal/parameter_encoding.rb
new file mode 100644
index 0000000000..a278c5d011
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/parameter_encoding.rb
@@ -0,0 +1,30 @@
+module ActionController
+ # Allows encoding to be specified per parameter per action.
+ module ParameterEncoding
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def inherited(klass) # :nodoc:
+ super
+ klass.setup_param_encode
+ end
+
+ def setup_param_encode # :nodoc:
+ @_parameter_encodings = {}
+ end
+
+ def encoding_for_param(action, param) # :nodoc:
+ if @_parameter_encodings[action.to_s] && @_parameter_encodings[action.to_s][param.to_s]
+ @_parameter_encodings[action.to_s][param.to_s]
+ else
+ ::Encoding::UTF_8
+ end
+ end
+
+ def parameter_encoding(action, param_name, encoding)
+ @_parameter_encodings[action.to_s] ||= {}
+ @_parameter_encodings[action.to_s][param_name.to_s] = encoding
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index ccedecd6f4..3a6bc92b3c 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -33,12 +33,14 @@ module ActionController
TestSession.new
end
+ attr_reader :controller_class
+
# Create a new test request with default `env` values
- def self.create
+ def self.create(controller_class)
env = {}
env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
env["rack.request.cookie_hash"] = {}.with_indifferent_access
- new(default_env.merge(env), new_session)
+ new(default_env.merge(env), new_session, controller_class)
end
def self.default_env
@@ -46,11 +48,12 @@ module ActionController
end
private_class_method :default_env
- def initialize(env, session)
+ def initialize(env, session, controller_class)
super(env)
self.session = session
self.session_options = TestSession::DEFAULT_OPTIONS
+ @controller_class = controller_class
@custom_param_parsers = {
xml: lambda { |raw_post| Hash.from_xml(raw_post)["hash"] }
}
@@ -497,7 +500,7 @@ module ActionController
@request.set_header "HTTP_COOKIE", cookies.to_header
@request.delete_header "action_dispatch.cookies"
- @request = TestRequest.new scrub_env!(@request.env), @request.session
+ @request = TestRequest.new scrub_env!(@request.env), @request.session, @controller.class
@response = build_response @response_klass
@response.request = @request
@controller.recycle!
@@ -591,7 +594,7 @@ module ActionController
end
end
- @request = TestRequest.create
+ @request = TestRequest.create(@controller.class)
@response = build_response @response_klass
@response.request = @request
@@ -668,11 +671,6 @@ module ActionController
end
end
end
-
- def html_format?(parameters)
- return true unless parameters.key?(:format)
- Mime.fetch(parameters[:format]) { Mime["html"] }.html?
- end
end
include Behavior
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index 91c45767ef..d5eef2987d 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -3,7 +3,7 @@ module ActionDispatch
# Provides access to the request's HTTP headers from the environment.
#
# env = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" }
- # headers = ActionDispatch::Http::Headers.new(env)
+ # headers = ActionDispatch::Http::Headers.from_hash(env)
# headers["Content-Type"] # => "text/plain"
# headers["User-Agent"] # => "curl/7.43.0"
#
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index f25e50f9f3..42e80b9bf5 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -37,6 +37,7 @@ module ActionDispatch
query_parameters.dup
end
params.merge!(path_parameters)
+ params = set_custom_encoding(params)
set_header("action_dispatch.request.parameters", params)
params
end
@@ -64,6 +65,21 @@ module ActionDispatch
private
+ def set_custom_encoding(params)
+ action = params[:action]
+ params.each do |k, v|
+ if v.is_a?(String) && v.encoding != encoding_template(action, k)
+ params[k] = v.force_encoding(encoding_template(action, k))
+ end
+ end
+
+ params
+ end
+
+ def encoding_template(action, param)
+ controller_class.encoding_for_param(action, param)
+ end
+
def parse_formatted_parameters(parsers)
return yield if content_length.zero? || content_mime_type.nil?
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 46409a325e..e7cc6d5f31 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -69,6 +69,7 @@ module ActionDispatch
PASS_NOT_FOUND = Class.new { # :nodoc:
def self.action(_); self; end
def self.call(_); [404, {"X-Cascade" => "pass"}, []]; end
+ def self.encoding_for_param(action, param); ::Encoding::UTF_8; end
}
def controller_class
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index cba67b2839..2ea4a6c130 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -184,7 +184,7 @@ module ActionDispatch
end
# Assume given controller
- request = ActionController::TestRequest.create
+ request = ActionController::TestRequest.create @controller.class
if path =~ %r{://}
fail_on(URI::InvalidURIError, msg) do
diff --git a/actionpack/test/abstract/translation_test.rb b/actionpack/test/abstract/translation_test.rb
index 1e17cb9777..0c4071df8d 100644
--- a/actionpack/test/abstract/translation_test.rb
+++ b/actionpack/test/abstract/translation_test.rb
@@ -9,7 +9,8 @@ module AbstractController
class TranslationControllerTest < ActiveSupport::TestCase
def setup
@controller = TranslationController.new
- I18n.backend.store_translations(:en, one: {
+ I18n.backend.store_translations(:en,
+ one: {
two: "bar",
},
abstract_controller: {
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 0c77de3c16..7bff21b5a2 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -122,27 +122,19 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
# Stub Rails dispatcher so it does not get controller references and
# simply return the controller#action as Rack::Body.
class NullController < ::ActionController::Metal
- def initialize(controller_name)
- @controller = controller_name
- end
-
- def make_response!(request)
- self.class.make_response! request
- end
-
- def dispatch(action, req, res)
- [200, {"Content-Type" => "text/html"}, ["#{@controller}##{action}"]]
+ def self.dispatch(action, req, res)
+ [200, {"Content-Type" => "text/html"}, ["#{req.params[:controller]}##{action}"]]
end
end
- class NullControllerRequest < DelegateClass(ActionDispatch::Request)
+ class NullControllerRequest < ActionDispatch::Request
def controller_class
- NullController.new params[:controller]
+ NullController
end
end
def make_request(env)
- NullControllerRequest.new super
+ NullControllerRequest.new env
end
end
diff --git a/actionpack/test/controller/new_base/render_action_test.rb b/actionpack/test/controller/new_base/render_action_test.rb
index e88f83b594..4b59a3d676 100644
--- a/actionpack/test/controller/new_base/render_action_test.rb
+++ b/actionpack/test/controller/new_base/render_action_test.rb
@@ -258,7 +258,8 @@ end
module RenderActionWithBothLayouts
class BasicController < ActionController::Base
- self.view_paths = [ActionView::FixtureResolver.new( "render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!",
+ self.view_paths = [ActionView::FixtureResolver.new(
+ "render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "Oh Hi <%= yield %> Bye",
"layouts/render_action_with_both_layouts/basic.html.erb" => "With Controller Layout! <%= yield %> Bye")]
diff --git a/actionpack/test/controller/parameter_encoding_test.rb b/actionpack/test/controller/parameter_encoding_test.rb
new file mode 100644
index 0000000000..69a72c000b
--- /dev/null
+++ b/actionpack/test/controller/parameter_encoding_test.rb
@@ -0,0 +1,73 @@
+require "abstract_unit"
+
+class ParameterEncodingController < ActionController::Base
+ parameter_encoding :test_bar, :bar, Encoding::ASCII_8BIT
+ parameter_encoding :test_baz, :baz, Encoding::ISO_8859_1
+ parameter_encoding :test_baz_to_ascii, :baz, Encoding::ASCII_8BIT
+
+ def test_foo
+ render body: params[:foo].encoding
+ end
+
+ def test_bar
+ render body: params[:bar].encoding
+ end
+
+ def test_baz
+ render body: params[:baz].encoding
+ end
+
+ def test_no_change_to_baz
+ render body: params[:baz].encoding
+ end
+
+ def test_baz_to_ascii
+ render body: params[:baz].encoding
+ end
+end
+
+class ParameterEncodingTest < ActionController::TestCase
+ tests ParameterEncodingController
+
+ test "properly transcodes UTF8 parameters into declared encodings" do
+ post :test_foo, params: {"foo" => "foo", "bar" => "bar", "baz" => "baz"}
+
+ assert_response :success
+ assert_equal "UTF-8", @response.body
+ end
+
+ test "properly transcodes ASCII_8BIT parameters into declared encodings" do
+ post :test_bar, params: {"foo" => "foo", "bar" => "bar", "baz" => "baz"}
+
+ assert_response :success
+ assert_equal "ASCII-8BIT", @response.body
+ end
+
+ test "properly transcodes ISO_8859_1 parameters into declared encodings" do
+ post :test_baz, params: {"foo" => "foo", "bar" => "bar", "baz" => "baz"}
+
+ assert_response :success
+ assert_equal "ISO-8859-1", @response.body
+ end
+
+ test "does not transcode parameters when not specified" do
+ post :test_no_change_to_baz, params: {"foo" => "foo", "bar" => "bar", "baz" => "baz"}
+
+ assert_response :success
+ assert_equal "UTF-8", @response.body
+ end
+
+ test "respects different encoding declarations for a param per action" do
+ post :test_baz_to_ascii, params: {"foo" => "foo", "bar" => "bar", "baz" => "baz"}
+
+ assert_response :success
+ assert_equal "ASCII-8BIT", @response.body
+ end
+
+ test "does not raise an error when passed a param declared as ASCII-8BIT that contains invalid bytes" do
+ get :test_bar, params: { "bar" => URI.parser.escape("bar\xE2baz".b) }
+
+ assert_response :success
+ assert_equal "ASCII-8BIT", @response.body
+ end
+end
diff --git a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb
index 9c9749c037..cd7c98f112 100644
--- a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb
+++ b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb
@@ -19,7 +19,8 @@ class AlwaysPermittedParametersTest < ActiveSupport::TestCase
end
test "permits parameters that are whitelisted" do
- params = ActionController::Parameters.new( book: { pages: 65 },
+ params = ActionController::Parameters.new(
+ book: { pages: 65 },
format: "json")
permitted = params.permit book: [:pages]
assert permitted.permitted?
diff --git a/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb b/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb
index bf2c3d1ed2..0358fd9976 100644
--- a/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb
+++ b/actionpack/test/controller/parameters/log_on_unpermitted_params_test.rb
@@ -11,7 +11,8 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase
end
test "logs on unexpected param" do
- params = ActionController::Parameters.new( book: { pages: 65 },
+ params = ActionController::Parameters.new(
+ book: { pages: 65 },
fishing: "Turnips")
assert_logged("Unpermitted parameter: fishing") do
@@ -20,7 +21,8 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase
end
test "logs on unexpected params" do
- params = ActionController::Parameters.new( book: { pages: 65 },
+ params = ActionController::Parameters.new(
+ book: { pages: 65 },
fishing: "Turnips",
car: "Mersedes")
@@ -30,7 +32,8 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase
end
test "logs on unexpected nested param" do
- params = ActionController::Parameters.new( book: { pages: 65, title: "Green Cats and where to find then." })
+ params = ActionController::Parameters.new(
+ book: { pages: 65, title: "Green Cats and where to find then." })
assert_logged("Unpermitted parameter: title") do
params.permit(book: [:pages])
@@ -38,7 +41,8 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase
end
test "logs on unexpected nested params" do
- params = ActionController::Parameters.new( book: { pages: 65, title: "Green Cats and where to find then.", author: "G. A. Dog" })
+ params = ActionController::Parameters.new(
+ book: { pages: 65, title: "Green Cats and where to find then.", author: "G. A. Dog" })
assert_logged("Unpermitted parameters: title, author") do
params.permit(book: [:pages])
diff --git a/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb b/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb
index 44e39135a2..88fb477c10 100644
--- a/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb
+++ b/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb
@@ -3,7 +3,8 @@ require "action_controller/metal/strong_parameters"
class MultiParameterAttributesTest < ActiveSupport::TestCase
test "permitted multi-parameter attribute keys" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
"shipped_at(1i)" => "2012",
"shipped_at(2i)" => "3",
"shipped_at(3i)" => "25",
diff --git a/actionpack/test/controller/parameters/nested_parameters_permit_test.rb b/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
index e3f1ba5f0a..f0155477c4 100644
--- a/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
@@ -7,7 +7,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "permitted nested parameters" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
title: "Romeo and Juliet",
authors: [{
name: "William Shakespeare",
@@ -43,7 +44,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "permitted nested parameters with a string or a symbol as a key" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
"authors" => [
{ name: "William Shakespeare", born: "1564-04-26" },
{ name: "Christopher Marlowe" }
@@ -66,7 +68,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "nested arrays with strings" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
genres: ["Tragedy"]
})
@@ -75,7 +78,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "permit may specify symbols or strings" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
title: "Romeo and Juliet",
author: "William Shakespeare"
},
@@ -88,7 +92,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "nested array with strings that should be hashes" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
genres: ["Tragedy"]
})
@@ -97,7 +102,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "nested array with strings that should be hashes and additional values" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
title: "Romeo and Juliet",
genres: ["Tragedy"]
})
@@ -108,7 +114,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "nested string that should be a hash" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
genre: "Tragedy"
})
@@ -117,7 +124,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "fields_for-style nested params" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
authors_attributes: {
'0': { name: "William Shakespeare", age_of_death: "52" },
'1': { name: "Unattributed Assistant" },
@@ -136,7 +144,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "fields_for-style nested params with negative numbers" do
- params = ActionController::Parameters.new( book: {
+ params = ActionController::Parameters.new(
+ book: {
authors_attributes: {
'-1': { name: "William Shakespeare", age_of_death: "52" },
'-2': { name: "Unattributed Assistant" }
@@ -153,7 +162,8 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
end
test "nested number as key" do
- params = ActionController::Parameters.new( product: {
+ params = ActionController::Parameters.new(
+ product: {
properties: {
"0" => "prop0",
"1" => "prop1"
diff --git a/actionpack/test/controller/parameters/raise_on_unpermitted_params_test.rb b/actionpack/test/controller/parameters/raise_on_unpermitted_params_test.rb
index bcb16eaf89..8fab7b28e9 100644
--- a/actionpack/test/controller/parameters/raise_on_unpermitted_params_test.rb
+++ b/actionpack/test/controller/parameters/raise_on_unpermitted_params_test.rb
@@ -11,7 +11,8 @@ class RaiseOnUnpermittedParamsTest < ActiveSupport::TestCase
end
test "raises on unexpected params" do
- params = ActionController::Parameters.new( book: { pages: 65 },
+ params = ActionController::Parameters.new(
+ book: { pages: 65 },
fishing: "Turnips")
assert_raises(ActionController::UnpermittedParameters) do
@@ -20,7 +21,8 @@ class RaiseOnUnpermittedParamsTest < ActiveSupport::TestCase
end
test "raises on unexpected nested params" do
- params = ActionController::Parameters.new( book: { pages: 65, title: "Green Cats and where to find then." })
+ params = ActionController::Parameters.new(
+ book: { pages: 65, title: "Green Cats and where to find then." })
assert_raises(ActionController::UnpermittedParameters) do
params.permit(book: [:pages])
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 05293dd94c..9f0e3bff15 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -29,7 +29,8 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
def test_route_generation_escapes_unsafe_path_characters
assert_equal "/content/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2",
- url_for(@set, controller: "content",
+ url_for(@set,
+ controller: "content",
action: "act#{@segment}ion",
variable: "var#{@segment}iable",
additional: ["add#{@segment}itional-1", "add#{@segment}itional-2"])
@@ -45,7 +46,8 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
def test_route_generation_allows_passing_non_string_values_to_generated_helper
assert_equal "/content/action/variable/1/2",
- url_for(@set, controller: "content",
+ url_for(@set,
+ controller: "content",
action: "action",
variable: "variable",
additional: [1, 2])
@@ -776,7 +778,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
end
end
- assert_equal "/journal", url_for(rs, controller: "content",
+ assert_equal "/journal", url_for(rs,
+ controller: "content",
action: "list_journal",
date: nil,
user_id: nil)
diff --git a/actionpack/test/journey/route_test.rb b/actionpack/test/journey/route_test.rb
index cce5c2ae37..886cf857e8 100644
--- a/actionpack/test/journey/route_test.rb
+++ b/actionpack/test/journey/route_test.rb
@@ -50,7 +50,8 @@ module ActionDispatch
path = Path::Pattern.from_string "/:controller/*extra"
route = Route.build("name", nil, path, {}, [],
controller: "foo", action: "bar")
- assert_equal "/foo/himom", route.format( controller: "foo",
+ assert_equal "/foo/himom", route.format(
+ controller: "foo",
extra: "himom")
end
@@ -58,7 +59,8 @@ module ActionDispatch
path = Path::Pattern.from_string "/:controller(/:action(/:id(.:format)))"
route = Route.build("name", nil, path, {action: "bar"}, [], controller: "foo")
- assert_equal "/foo/bar/10", route.format( controller: "foo",
+ assert_equal "/foo/bar/10", route.format(
+ controller: "foo",
action: "bar",
id: 10)
end
diff --git a/actionview/bin/test b/actionview/bin/test
index 404cabba51..84a05bba08 100755
--- a/actionview/bin/test
+++ b/actionview/bin/test
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
-COMPONENT_ROOT = File.expand_path("../../", __FILE__)
+
+COMPONENT_ROOT = File.expand_path("..", __dir__)
require File.expand_path("../tools/test", COMPONENT_ROOT)
+
exit Minitest.run(ARGV)
diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb
index 030d07845b..4950f272a4 100644
--- a/actionview/lib/action_view/helpers/tag_helper.rb
+++ b/actionview/lib/action_view/helpers/tag_helper.rb
@@ -88,9 +88,9 @@ module ActionView
if value.is_a?(Array)
value = escape ? safe_join(value, " ") : value.join(" ")
else
- value = escape ? ERB::Util.unwrapped_html_escape(value) : value
+ value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s
end
- %(#{key}="#{value}")
+ %(#{key}="#{value.gsub(/"/, '&quot;'.freeze)}")
end
private
diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb
index 42fa17d1e0..2945aceb3e 100644
--- a/actionview/lib/action_view/test_case.rb
+++ b/actionview/lib/action_view/test_case.rb
@@ -24,7 +24,7 @@ module ActionView
def initialize
super
self.class.controller_path = ""
- @request = ActionController::TestRequest.create
+ @request = ActionController::TestRequest.create(self.class)
@response = ActionDispatch::TestResponse.new
@request.env.delete("PATH_INFO")
diff --git a/actionview/test/actionpack/controller/view_paths_test.rb b/actionview/test/actionpack/controller/view_paths_test.rb
index e676a2ecd4..9471c76921 100644
--- a/actionview/test/actionpack/controller/view_paths_test.rb
+++ b/actionview/test/actionpack/controller/view_paths_test.rb
@@ -23,9 +23,9 @@ class ViewLoadPathsTest < ActionController::TestCase
end
def setup
- @request = ActionController::TestRequest.create
- @response = ActionDispatch::TestResponse.new
@controller = TestController.new
+ @request = ActionController::TestRequest.create(@controller.class)
+ @response = ActionDispatch::TestResponse.new
@paths = TestController.view_paths
end
@@ -131,7 +131,7 @@ class ViewLoadPathsTest < ActionController::TestCase
"Decorated body",
template.identifier,
template.handler,
- virtual_path: template.virtual_path,
+ virtual_path: template.virtual_path,
format: template.formats
)
end
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index 590e79d114..70f690478d 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -16,7 +16,8 @@ class FormHelperTest < ActionView::TestCase
setup do
# Create "label" locale for testing I18n label helpers
- I18n.backend.store_translations "label", activemodel: {
+ I18n.backend.store_translations "label",
+ activemodel: {
attributes: {
post: {
cost: "Total cost"
@@ -47,7 +48,8 @@ class FormHelperTest < ActionView::TestCase
}
# Create "submit" locale for testing I18n submit helpers
- I18n.backend.store_translations "submit", helpers: {
+ I18n.backend.store_translations "submit",
+ helpers: {
submit: {
create: "Create %{model}",
update: "Confirm %{model} changes",
@@ -58,7 +60,8 @@ class FormHelperTest < ActionView::TestCase
}
}
- I18n.backend.store_translations "placeholder", activemodel: {
+ I18n.backend.store_translations "placeholder",
+ activemodel: {
attributes: {
post: {
cost: "Total cost"
diff --git a/actionview/test/template/tag_helper_test.rb b/actionview/test/template/tag_helper_test.rb
index 281fec7291..d07312ace3 100644
--- a/actionview/test/template/tag_helper_test.rb
+++ b/actionview/test/template/tag_helper_test.rb
@@ -59,6 +59,14 @@ class TagHelperTest < ActionView::TestCase
assert_equal "<p included=\"\"></p>", tag.p(included: "")
end
+ def test_tag_options_accepts_symbol_option_when_not_escaping
+ assert_equal "<p value=\"symbol\" />", tag("p", { value: :symbol }, false, false)
+ end
+
+ def test_tag_options_accepts_integer_option_when_not_escaping
+ assert_equal "<p value=\"42\" />", tag("p", { value: 42 }, false, false)
+ end
+
def test_tag_options_converts_boolean_option
assert_dom_equal '<p disabled="disabled" itemscope="itemscope" multiple="multiple" readonly="readonly" allowfullscreen="allowfullscreen" seamless="seamless" typemustmatch="typemustmatch" sortable="sortable" default="default" inert="inert" truespeed="truespeed" />',
tag("p", disabled: true, itemscope: true, multiple: true, readonly: true, allowfullscreen: true, seamless: true, typemustmatch: true, sortable: true, default: true, inert: true, truespeed: true)
@@ -274,6 +282,16 @@ class TagHelperTest < ActionView::TestCase
assert_equal '<p class="song> play&gt;"></p>', tag.p(class: [raw("song>"), "play>"])
end
+ def test_tag_does_not_honor_html_safe_double_quotes_as_attributes
+ assert_dom_equal '<p title="&quot;">content</p>',
+ content_tag('p', "content", title: '"'.html_safe)
+ end
+
+ def test_data_tag_does_not_honor_html_safe_double_quotes_as_attributes
+ assert_dom_equal '<p data-title="&quot;">content</p>',
+ content_tag('p', "content", data: { title: '"'.html_safe })
+ end
+
def test_skip_invalid_escaped_attributes
["&1;", "&#1dfa3;", "& #123;"].each do |escaped|
assert_equal %(<a href="#{escaped.gsub(/&/, '&amp;')}" />), tag("a", href: escaped)
diff --git a/activemodel/bin/test b/activemodel/bin/test
index 404cabba51..84a05bba08 100755
--- a/activemodel/bin/test
+++ b/activemodel/bin/test
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
-COMPONENT_ROOT = File.expand_path("../../", __FILE__)
+
+COMPONENT_ROOT = File.expand_path("..", __dir__)
require File.expand_path("../tools/test", COMPONENT_ROOT)
+
exit Minitest.run(ARGV)
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index b6ab7ab6b0..45ef14013a 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -439,7 +439,8 @@ module ActiveModel
return message if attribute == :base
attr_name = attribute.to_s.tr(".", "_").humanize
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
- I18n.t(:"errors.format", default: "%{attribute} %{message}",
+ I18n.t(:"errors.format",
+ default: "%{attribute} %{message}",
attribute: attr_name,
message: message)
end
diff --git a/activemodel/test/cases/validations/confirmation_validation_test.rb b/activemodel/test/cases/validations/confirmation_validation_test.rb
index a980628765..c13017d825 100644
--- a/activemodel/test/cases/validations/confirmation_validation_test.rb
+++ b/activemodel/test/cases/validations/confirmation_validation_test.rb
@@ -55,7 +55,8 @@ class ConfirmationValidationTest < ActiveModel::TestCase
@old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
I18n.load_path.clear
I18n.backend = I18n::Backend::Simple.new
- I18n.backend.store_translations("en", errors: { messages: { confirmation: "doesn't match %{attribute}" } },
+ I18n.backend.store_translations("en",
+ errors: { messages: { confirmation: "doesn't match %{attribute}" } },
activemodel: { attributes: { topic: { title: "Test Title"} } })
Topic.validates_confirmation_of(:title)
diff --git a/activerecord/bin/test b/activerecord/bin/test
index 822e303ad8..23add35d45 100755
--- a/activerecord/bin/test
+++ b/activerecord/bin/test
@@ -1,6 +1,8 @@
#!/usr/bin/env ruby
-COMPONENT_ROOT = File.expand_path("../../", __FILE__)
+
+COMPONENT_ROOT = File.expand_path("..", __dir__)
require File.expand_path("../tools/test", COMPONENT_ROOT)
+
module Minitest
def self.plugin_active_record_options(opts, options)
opts.separator ""
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index d2ebc36fff..d0aefcef68 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -1208,7 +1208,7 @@ module ActiveRecord
checks << lambda { |i| i.columns.join("_and_") == column_names.join("_and_") }
end
- raise ArgumentError "No name or columns specified" if checks.none?
+ raise ArgumentError, "No name or columns specified" if checks.none?
matching_indexes = indexes(table_name).select { |i| checks.all? { |check| check[i] } }
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index a7869f44ea..be6b55e53c 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -78,10 +78,12 @@ module ActiveRecord
def raw_config
if uri.opaque
- query_hash.merge( "adapter" => @adapter,
+ query_hash.merge(
+ "adapter" => @adapter,
"database" => uri.opaque)
else
- query_hash.merge( "adapter" => @adapter,
+ query_hash.merge(
+ "adapter" => @adapter,
"username" => uri.user,
"password" => uri.password,
"port" => uri.port,
diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb
index a4a06a2da4..d3c65f3d94 100644
--- a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb
@@ -81,6 +81,12 @@ class PostgresqlActiveSchemaTest < ActiveRecord::PostgreSQLTestCase
assert_equal expected, remove_index(:people, name: "index_people_on_last_name", algorithm: :concurrently)
end
+ def test_remove_index_with_wrong_option
+ assert_raises ArgumentError do
+ remove_index(:people, coulmn: :last_name)
+ end
+ end
+
private
def method_missing(method_symbol, *arguments)
ActiveRecord::Base.connection.send(method_symbol, *arguments)
diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
index c4f174e470..ec6ae39835 100644
--- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -283,7 +283,8 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
end
def test_habtm_collection_size_from_params
- devel = Developer.new( projects_attributes: {
+ devel = Developer.new(
+ projects_attributes: {
"0" => {}
})
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 73ca83f21b..cd896e5948 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -279,7 +279,8 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_initialize_with_attributes
- topic = Topic.new( "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23")
+ topic = Topic.new(
+ "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23")
assert_equal("initialized from attributes", topic.title)
end
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index f0cf02ce54..788277faea 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -596,7 +596,8 @@ module NestedAttributesOnACollectionAssociationTests
end
def test_should_save_only_one_association_on_create
- pirate = Pirate.create!( :catchphrase => "Arr",
+ pirate = Pirate.create!(
+ :catchphrase => "Arr",
association_getter => { "foo" => { name: "Grace OMalley" } })
assert_equal 1, pirate.reload.send(@association_name).count
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 57dc963b62..e293770725 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -967,7 +967,8 @@ class PersistenceTest < ActiveRecord::TestCase
self.table_name = :widgets
end
- instance = widget.create!( name: "Bob",
+ instance = widget.create!(
+ name: "Bob",
created_at: 1.day.ago,
updated_at: 1.day.ago)
diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb
index 13007e2e73..a46123f451 100644
--- a/activerecord/test/cases/scoping/relation_scoping_test.rb
+++ b/activerecord/test/cases/scoping/relation_scoping_test.rb
@@ -246,7 +246,7 @@ class NestedRelationScopingTest < ActiveRecord::TestCase
devs = Developer.all
sql = devs.to_sql
assert_match "(salary = 80000)", sql
- assert_match /LIMIT 10|ROWNUM <= 10|FETCH FIRST 10 ROWS ONLY/, sql
+ assert_match(/LIMIT 10|ROWNUM <= 10|FETCH FIRST 10 ROWS ONLY/, sql)
end
end
end
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index 76510cb80d..5d9aa99497 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -156,17 +156,15 @@ class ValidationsTest < ActiveRecord::TestCase
end
def test_numericality_validation_with_mutation
- Topic.class_eval do
+ klass = Class.new(Topic) do
attribute :wibble, :string
validates_numericality_of :wibble, only_integer: true
end
- topic = Topic.new(wibble: "123-4567")
+ topic = klass.new(wibble: "123-4567")
topic.wibble.gsub!("-", "")
assert topic.valid?
- ensure
- Topic.reset_column_information
end
def test_acceptance_validator_doesnt_require_db_connection
diff --git a/activesupport/bin/test b/activesupport/bin/test
index 404cabba51..84a05bba08 100755
--- a/activesupport/bin/test
+++ b/activesupport/bin/test
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
-COMPONENT_ROOT = File.expand_path("../../", __FILE__)
+
+COMPONENT_ROOT = File.expand_path("..", __dir__)
require File.expand_path("../tools/test", COMPONENT_ROOT)
+
exit Minitest.run(ARGV)
diff --git a/guides/rails_guides/markdown.rb b/guides/rails_guides/markdown.rb
index e6c9fea87e..33563d669c 100644
--- a/guides/rails_guides/markdown.rb
+++ b/guides/rails_guides/markdown.rb
@@ -54,7 +54,8 @@ module RailsGuides
end
def engine
- @engine ||= Redcarpet::Markdown.new(Renderer, no_intra_emphasis: true,
+ @engine ||= Redcarpet::Markdown.new(Renderer,
+ no_intra_emphasis: true,
fenced_code_blocks: true,
autolink: true,
strikethrough: true,
diff --git a/guides/source/action_cable_overview.md b/guides/source/action_cable_overview.md
index 02db86888c..118b0b52b2 100644
--- a/guides/source/action_cable_overview.md
+++ b/guides/source/action_cable_overview.md
@@ -242,10 +242,10 @@ WebNotificationsChannel.broadcast_to(
The `WebNotificationsChannel.broadcast_to` call places a message in the current
subscription adapter (Redis by default)'s pubsub queue under a separate
broadcasting name for each user. For a user with an ID of 1, the broadcasting
-name would be `web_notifications_1`.
+name would be `web_notifications:1`.
The channel has been instructed to stream everything that arrives at
-`web_notifications_1` directly to the client by invoking the `received`
+`web_notifications:1` directly to the client by invoking the `received`
callback.
### Subscriptions
@@ -313,7 +313,7 @@ App.cable.subscriptions.create { channel: "ChatChannel", room: "Best Room" },
```ruby
# Somewhere in your app this is called, perhaps
# from a NewCommentJob.
-ChatChannel.broadcast_to(
+ActionCable.server.broadcast(
"chat_#{room}",
sent_by: 'Paul',
body: 'This is a cool chat app.'
diff --git a/guides/source/active_model_basics.md b/guides/source/active_model_basics.md
index e834aeadb1..732e553c62 100644
--- a/guides/source/active_model_basics.md
+++ b/guides/source/active_model_basics.md
@@ -416,7 +416,6 @@ the Active Model API.
```ruby
class Person
include ActiveModel::Model
-
end
```
@@ -467,7 +466,7 @@ In order to make this work, the model must have an accessor named `password_dige
The `has_secure_password` will add the following validations on the `password` accessor:
1. Password should be present.
-2. Password should be equal to its confirmation.
+2. Password should be equal to its confirmation (provided +password_confirmation+ is passed along).
3. The maximum length of a password is 72 (required by `bcrypt` on which ActiveModel::SecurePassword depends)
#### Examples
@@ -493,6 +492,10 @@ person.valid? # => false
person.password = person.password_confirmation = 'a' * 100
person.valid? # => false
+# When only password is supplied with no password_confirmation.
+person.password = 'aditya'
+person.valid? # => true
+
# When all validations are passed.
person.password = person.password_confirmation = 'aditya'
person.valid? # => true
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 8ffd0d033d..6f941d0e4e 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1251,8 +1251,9 @@ articles, all the articles would still be loaded. By using `joins` (an INNER
JOIN), the join conditions **must** match, otherwise no records will be
returned.
-
-
+NOTE: If an association is eager loaded as part of a join, any fields from a custom select clause will not present be on the loaded models.
+This is because it is ambiguous whether they should appear on the parent record, or the child.
+
Scopes
------
diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md
index cc84ecb216..a1b0029c47 100644
--- a/guides/source/caching_with_rails.md
+++ b/guides/source/caching_with_rails.md
@@ -512,6 +512,30 @@ class ProductsController < ApplicationController
end
```
+Sometimes we want to cache response, for example a static page, that never gets
+expired. To achieve this, we can use `http_cache_forever` helper and by doing
+so browser and proxies will cache it indefinitely.
+
+By default cached responses will be private, cached only on the user's web
+browser. To allow proxies to cache the response, set `public: true` to indicate
+that they can serve the cached response to all users.
+
+Using this helper, `last_modified` header is set to `Time.new(2011, 1, 1).utc`
+and `expires` header is set to a 100 years.
+
+WARNING: Use this method carefully as browser/proxy won't be able to invalidate
+the cached response unless browser cache is forcefully cleared.
+
+```ruby
+class HomeController < ApplicationController
+ def index
+ http_cache_forever(public: true) do
+ render
+ end
+ end
+end
+```
+
### Strong v/s Weak ETags
Rails generates weak ETags by default. Weak ETags allow semantically equivalent
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index e4fc7f4743..df3003a6a8 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -946,6 +946,7 @@ development that will end your tailing of development.log. Have all information
about your Rails app requests in the browser — in the Developer Tools panel.
Provides insight to db/rendering/total times, parameter list, rendered views and
more.
+* [Pry](https://github.com/pry/pry) An IRB alternative and runtime developer console.
References
----------
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index bf8ae0a5ee..0339849bfe 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -88,7 +88,8 @@ module Rails
end
def default_options
- super.merge( Port: ENV.fetch("PORT", 3000).to_i,
+ super.merge(
+ Port: ENV.fetch("PORT", 3000).to_i,
Host: ENV.fetch("HOST", "localhost").dup,
DoNotReverseLookup: true,
environment: (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development").dup,
diff --git a/railties/lib/rails/engine/commands_tasks.rb b/railties/lib/rails/engine/commands_tasks.rb
index ac0861328b..e21a7183fc 100644
--- a/railties/lib/rails/engine/commands_tasks.rb
+++ b/railties/lib/rails/engine/commands_tasks.rb
@@ -103,6 +103,8 @@ In addition to those commands, there are:
end
def rake_tasks
+ require_rake
+
return @rake_tasks if defined?(@rake_tasks)
load_generators
diff --git a/railties/test/engine/commands_tasks_test.rb b/railties/test/engine/commands_tasks_test.rb
new file mode 100644
index 0000000000..817175b9ef
--- /dev/null
+++ b/railties/test/engine/commands_tasks_test.rb
@@ -0,0 +1,24 @@
+require "abstract_unit"
+
+class Rails::Engine::CommandsTasksTest < ActiveSupport::TestCase
+ def setup
+ @destination_root = Dir.mktmpdir("bukkits")
+ Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` }
+ end
+
+ def teardown
+ FileUtils.rm_rf(@destination_root)
+ end
+
+ def test_help_command_work_inside_engine
+ output = capture(:stderr) do
+ Dir.chdir(plugin_path) { `bin/rails --help` }
+ end
+ assert_no_match "NameError", output
+ end
+
+ private
+ def plugin_path
+ "#{@destination_root}/bukkits"
+ end
+end
diff --git a/railties/test/json_params_parsing_test.rb b/railties/test/json_params_parsing_test.rb
new file mode 100644
index 0000000000..eac731a942
--- /dev/null
+++ b/railties/test/json_params_parsing_test.rb
@@ -0,0 +1,47 @@
+require "abstract_unit"
+require "action_dispatch"
+require "active_record"
+
+class JsonParamsParsingTest < ActionDispatch::IntegrationTest
+ test "prevent null query" do
+ # Make sure we have data to find
+ klass = Class.new(ActiveRecord::Base) do
+ def self.name; 'Foo'; end
+ establish_connection adapter: "sqlite3", database: ":memory:"
+ connection.create_table "foos" do |t|
+ t.string :title
+ t.timestamps null: false
+ end
+ end
+ klass.create
+ assert klass.first
+
+ app = ->(env) {
+ request = ActionDispatch::Request.new env
+ params = ActionController::Parameters.new request.parameters
+ if params[:t]
+ klass.find_by_title(params[:t])
+ else
+ nil
+ end
+ }
+
+ assert_nil app.call(make_env({ 't' => nil }))
+ assert_nil app.call(make_env({ 't' => [nil] }))
+
+ [[[nil]], [[[nil]]]].each do |data|
+ assert_nil app.call(make_env({ 't' => data }))
+ end
+ end
+
+ private
+ def make_env json
+ data = JSON.dump json
+ content_length = data.length
+ {
+ 'CONTENT_LENGTH' => content_length,
+ 'CONTENT_TYPE' => 'application/json',
+ 'rack.input' => StringIO.new(data)
+ }
+ end
+end