From f650e0324207e46ed5240380e60bdf1e2a5023a6 Mon Sep 17 00:00:00 2001
From: Jeff Kreeftmeijer <jeff@kreeftmeijer.nl>
Date: Thu, 19 May 2016 15:20:03 +0200
Subject: Use `#performed?` to terminate controller callbacks

Since 69009f, `ActionController::Metal::DataStreaming#send_file` doesn't
set `@_response_body` anymore.

`AbstractController::Callbacks` used `@_response_body` in its callback
terminator, so it failed to halt the callback cycle when using `#send_file`
from a `before_action`.

Instead, it now uses `#performed?` on `AbstractController::Base` and
`ActionController::Metal`, which checks `response.committed?`, besides
 checking if `@_response_body` is set, if possible.

Example application: https://gist.github.com/jeffkreeftmeijer/78ae4572f36b198e729724b0cf79ef8e
---
 actionpack/test/controller/send_file_test.rb | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

(limited to 'actionpack/test')

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 }
-- 
cgit v1.2.3