aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/abstract_controller/base.rb7
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb2
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb39
-rw-r--r--actionpack/lib/action_controller/renderer.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/test/controller/integration_test.rb16
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb6
-rw-r--r--actionpack/test/controller/render_test.rb7
-rw-r--r--actionpack/test/controller/send_file_test.rb15
-rw-r--r--actionpack/test/dispatch/cookies_test.rb4
-rw-r--r--actionpack/test/dispatch/routing_test.rb30
12 files changed, 107 insertions, 25 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index d4317399ed..aa06f70433 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -150,6 +150,13 @@ module AbstractController
_find_action_name(action_name)
end
+ # Tests if a response body is set. Used to determine if the
+ # +process_action+ callback needs to be terminated in
+ # +AbstractController::Callbacks+.
+ def performed?
+ response_body
+ end
+
# Returns true if the given controller is capable of rendering
# a path. A subclass of +AbstractController::Base+
# may return false. An Email controller for example does not
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index d63ce9c1c3..3ef8da86fa 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -9,7 +9,7 @@ module AbstractController
included do
define_callbacks :process_action,
- terminator: ->(controller, result_lambda) { result_lambda.call if result_lambda.is_a?(Proc); controller.response_body },
+ terminator: ->(controller, result_lambda) { result_lambda.call if result_lambda.is_a?(Proc); controller.performed? },
skip_after_callbacks_if_terminated: true
end
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index a6fb0dbe1d..4ba2c26949 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -122,7 +122,7 @@ module AbstractController
def _normalize_render(*args, &block)
options = _normalize_args(*args, &block)
#TODO: remove defined? when we restore AP <=> AV dependency
- if defined?(request) && request.variant.present?
+ if defined?(request) && !request.nil? && request.variant.present?
options[:variant] = request.variant
end
_normalize_options(options)
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 46589901fd..b326695ce2 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -58,8 +58,7 @@ module ActionController
# })
#
# permitted = params.require(:person).permit(:name, :age)
- # permitted # => {"name"=>"Francesco", "age"=>22}
- # permitted.class # => ActionController::Parameters
+ # permitted # => <ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>
# permitted.permitted? # => true
#
# Person.first.update!(permitted)
@@ -87,7 +86,7 @@ module ActionController
#
# params = ActionController::Parameters.new(a: "123", b: "456")
# params.permit(:c)
- # # => {}
+ # # => <ActionController::Parameters {} permitted: true>
#
# ActionController::Parameters.action_on_unpermitted_parameters = :raise
#
@@ -107,6 +106,8 @@ module ActionController
# params["key"] # => "value"
class Parameters
cattr_accessor :permit_all_parameters, instance_accessor: false
+ self.permit_all_parameters = false
+
cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?,
@@ -255,7 +256,7 @@ module ActionController
# either present or the singleton +false+, returns said value:
#
# ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
- # # => {"name"=>"Francesco"}
+ # # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
#
# Otherwise raises <tt>ActionController::ParameterMissing</tt>:
#
@@ -276,12 +277,12 @@ module ActionController
# returned:
#
# params = ActionController::Parameters.new(user: { ... }, profile: { ... })
- # user_params, profile_params = params.require(:user, :profile)
+ # user_params, profile_params = params.require([:user, :profile])
#
# Otherwise, the method re-raises the first exception found:
#
# params = ActionController::Parameters.new(user: {}, profile: {})
- # user_params, profile_params = params.require(:user, :profile)
+ # user_params, profile_params = params.require([:user, :profile])
# # ActionController::ParameterMissing: param is missing or the value is empty: user
#
# Technically this method can be used to fetch terminal values:
@@ -374,13 +375,13 @@ module ActionController
# })
#
# params.require(:person).permit(:contact)
- # # => {}
+ # # => <ActionController::Parameters {} permitted: true>
#
# params.require(:person).permit(contact: :phone)
- # # => {"contact"=>{"phone"=>"555-1234"}}
+ # # => <ActionController::Parameters {"contact"=><ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>
#
# params.require(:person).permit(contact: [ :email, :phone ])
- # # => {"contact"=>{"email"=>"none@test.com", "phone"=>"555-1234"}}
+ # # => <ActionController::Parameters {"contact"=><ActionController::Parameters {"email"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>
def permit(*filters)
params = self.class.new
@@ -402,7 +403,7 @@ module ActionController
# returns +nil+.
#
# params = ActionController::Parameters.new(person: { name: 'Francesco' })
- # params[:person] # => {"name"=>"Francesco"}
+ # params[:person] # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
# params[:none] # => nil
def [](key)
convert_hashes_to_parameters(key, @parameters[key])
@@ -421,7 +422,7 @@ module ActionController
# is given, then that will be run and its result returned.
#
# params = ActionController::Parameters.new(person: { name: 'Francesco' })
- # params.fetch(: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"
@@ -457,8 +458,8 @@ module ActionController
# don't exist, returns an empty hash.
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
- # params.slice(:a, :b) # => {"a"=>1, "b"=>2}
- # params.slice(:d) # => {}
+ # params.slice(:a, :b) # => <ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
+ # params.slice(:d) # => <ActionController::Parameters {} permitted: false>
def slice(*keys)
new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
end
@@ -474,8 +475,8 @@ module ActionController
# filters out the given +keys+.
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
- # params.except(:a, :b) # => {"c"=>3}
- # params.except(:d) # => {"a"=>1,"b"=>2,"c"=>3}
+ # params.except(:a, :b) # => <ActionController::Parameters {"c"=>3} permitted: false>
+ # params.except(:d) # => <ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
def except(*keys)
new_instance_with_inherited_permitted_status(@parameters.except(*keys))
end
@@ -483,8 +484,8 @@ module ActionController
# Removes and returns the key/value pairs matching the given keys.
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
- # params.extract!(:a, :b) # => {"a"=>1, "b"=>2}
- # params # => {"c"=>3}
+ # params.extract!(:a, :b) # => <ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
+ # params # => <ActionController::Parameters {"c"=>3} permitted: false>
def extract!(*keys)
new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
end
@@ -494,7 +495,7 @@ module ActionController
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
# params.transform_values { |x| x * 2 }
- # # => {"a"=>2, "b"=>4, "c"=>6}
+ # # => <ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
def transform_values(&block)
if block
new_instance_with_inherited_permitted_status(
@@ -577,7 +578,7 @@ module ActionController
# params = ActionController::Parameters.new(a: 1)
# params.permit!
# params.permitted? # => true
- # copy_params = params.dup # => {"a"=>1}
+ # copy_params = params.dup # => <ActionController::Parameters {"a"=>1} permitted: true>
# copy_params.permitted? # => true
def dup
super.tap do |duplicate|
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index 5ff4a658ad..a8c8d66682 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -1,7 +1,7 @@
require 'active_support/core_ext/hash/keys'
module ActionController
- # ActionController::Renderer allows to render arbitrary templates
+ # ActionController::Renderer allows you to render arbitrary templates
# without requirement of being in controller actions.
#
# You get a concrete renderer class by invoking ActionController::Base#renderer.
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 8ff3b42a40..40b6500553 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -106,7 +106,7 @@ module ActionDispatch
@ast = ast
@anchor = anchor
@via = via
- @internal = options[:internal]
+ @internal = options.delete(:internal)
path_params = ast.find_all(&:symbol?).map(&:to_sym)
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 97571c1308..34fb3b1003 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -1147,6 +1147,22 @@ class IntegrationRequestEncodersTest < ActionDispatch::IntegrationTest
end
end
+ def test_standard_json_encoding_works
+ with_routing do |routes|
+ routes.draw do
+ ActiveSupport::Deprecation.silence do
+ post ':action' => FooController
+ end
+ end
+
+ post '/foos_json.json', params: { foo: 'fighters' }.to_json,
+ headers: { 'Content-Type' => 'application/json' }
+
+ assert_response :success
+ assert_equal({ 'foo' => 'fighters' }, response.parsed_body)
+ end
+ end
+
def test_encoding_as_json
post_to_foos as: :json do
assert_response :success
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index b75eb0e3bf..2eed2996f6 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -369,4 +369,10 @@ class ParametersPermitTest < ActiveSupport::TestCase
refute params.permit(foo: [:bar]).has_key?(:foo)
refute params.permit(foo: :bar).has_key?(:foo)
end
+
+ test '#permitted? is false by default' do
+ params = ActionController::Parameters.new
+
+ assert_equal false, params.permitted?
+ end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index f42efd35af..8d3134630d 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -564,6 +564,13 @@ class MetalRenderTest < ActionController::TestCase
end
end
+class ActionControllerBaseRenderTest < ActionController::TestCase
+ def test_direct_render_to_string
+ ac = ActionController::Base.new()
+ assert_equal "Hello world!", ac.render_to_string(template: 'test/hello_world')
+ end
+end
+
class ImplicitRenderTest < ActionController::TestCase
tests ImplicitRenderTestController
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 2820425c31..9df70dacbf 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -11,6 +11,8 @@ class SendFileController < ActionController::Base
include ActionController::Testing
layout "layouts/standard" # to make sure layouts don't interfere
+ before_action :file, only: :file_from_before_action
+
attr_writer :options
def options
@options ||= {}
@@ -20,6 +22,10 @@ class SendFileController < ActionController::Base
send_file(file_path, options)
end
+ def file_from_before_action
+ raise 'No file sent from before action.'
+ end
+
def test_send_file_headers_bang
options = {
:type => Mime[:png],
@@ -192,6 +198,15 @@ class SendFileTest < ActionController::TestCase
assert_nil @controller.headers['Content-Disposition']
end
+ def test_send_file_from_before_action
+ response = nil
+ assert_nothing_raised { response = process('file_from_before_action') }
+ assert_not_nil response
+
+ assert_kind_of String, response.body
+ assert_equal file_data, response.body
+ end
+
%w(file data).each do |method|
define_method "test_send_#{method}_status" do
@controller.options = { :stream => false, :status => 500 }
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index dfcef14344..c7194cde4a 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -520,7 +520,7 @@ class CookiesTest < ActionController::TestCase
def test_accessing_nonexistent_signed_cookie_should_not_raise_an_invalid_signature
get :set_signed_cookie
- assert_nil @controller.send(:cookies).signed[:non_existant_attribute]
+ assert_nil @controller.send(:cookies).signed[:non_existent_attribute]
end
def test_encrypted_cookie_using_default_serializer
@@ -638,7 +638,7 @@ class CookiesTest < ActionController::TestCase
def test_accessing_nonexistent_encrypted_cookie_should_not_raise_invalid_message
get :set_encrypted_cookie
- assert_nil @controller.send(:cookies).encrypted[:non_existant_attribute]
+ assert_nil @controller.send(:cookies).encrypted[:non_existent_attribute]
end
def test_setting_invalid_encrypted_cookie_should_return_nil_when_accessing_it
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index ade4b0c381..75fdc9469f 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -4795,3 +4795,33 @@ class TestPathParameters < ActionDispatch::IntegrationTest
assert_equal "/ar | /ar/about", @response.body
end
end
+
+class TestInternalRoutingParams < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ get '/test_internal/:internal' => 'internal#internal'
+ end
+ end
+
+ class ::InternalController < ActionController::Base
+ def internal
+ head :ok
+ end
+ end
+
+ APP = build_app Routes
+
+ def app
+ APP
+ end
+
+ def test_paths_with_partial_dynamic_segments_are_recognised
+ get '/test_internal/123'
+ assert_equal 200, response.status
+
+ assert_equal(
+ { controller: 'internal', action: 'internal', internal: '123' },
+ request.path_parameters
+ )
+ end
+end