From 9f95767979579f5761cb0d2bcccb67f3662349c5 Mon Sep 17 00:00:00 2001
From: George Claghorn <george@basecamp.com>
Date: Thu, 17 May 2018 19:14:11 -0400
Subject: Permit opening a blob in a custom tempdir

---
 activestorage/app/models/active_storage/blob.rb |  4 ++--
 activestorage/lib/active_storage/analyzer.rb    |  6 +++++-
 activestorage/lib/active_storage/downloader.rb  | 11 ++++++-----
 activestorage/lib/active_storage/previewer.rb   |  2 +-
 activestorage/test/models/blob_test.rb          | 12 ++++++++++++
 5 files changed, 26 insertions(+), 9 deletions(-)

(limited to 'activestorage')

diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb
index 9bf0766843..134d3bb2d9 100644
--- a/activestorage/app/models/active_storage/blob.rb
+++ b/activestorage/app/models/active_storage/blob.rb
@@ -167,8 +167,8 @@ class ActiveStorage::Blob < ActiveRecord::Base
   end
 
   # Downloads the blob to a tempfile on disk. Yields the tempfile.
-  def open(&block)
-    ActiveStorage::Downloader.new(self).download_blob_to_tempfile(&block)
+  def open(tempdir: nil, &block)
+    ActiveStorage::Downloader.new(self, tempdir: tempdir).download_blob_to_tempfile(&block)
   end
 
 
diff --git a/activestorage/lib/active_storage/analyzer.rb b/activestorage/lib/active_storage/analyzer.rb
index 8dcfb9d7bd..caa25418a5 100644
--- a/activestorage/lib/active_storage/analyzer.rb
+++ b/activestorage/lib/active_storage/analyzer.rb
@@ -24,11 +24,15 @@ module ActiveStorage
     private
       # Downloads the blob to a tempfile on disk. Yields the tempfile.
       def download_blob_to_tempfile(&block) #:doc:
-        blob.open(&block)
+        blob.open tempdir: tempdir, &block
       end
 
       def logger #:doc:
         ActiveStorage.logger
       end
+
+      def tempdir #:doc:
+        Dir.tmpdir
+      end
   end
 end
diff --git a/activestorage/lib/active_storage/downloader.rb b/activestorage/lib/active_storage/downloader.rb
index 7f5b4936a5..0e7039e104 100644
--- a/activestorage/lib/active_storage/downloader.rb
+++ b/activestorage/lib/active_storage/downloader.rb
@@ -1,9 +1,10 @@
 # frozen_string_literal: true
 
 module ActiveStorage
-  class Downloader
-    def initialize(blob)
-      @blob = blob
+  class Downloader #:nodoc:
+    def initialize(blob, tempdir: nil)
+      @blob    = blob
+      @tempdir = tempdir
     end
 
     def download_blob_to_tempfile
@@ -14,10 +15,10 @@ module ActiveStorage
     end
 
     private
-      attr_reader :blob
+      attr_reader :blob, :tempdir
 
       def open_tempfile
-        file = Tempfile.open([ "ActiveStorage", tempfile_extension_with_delimiter ])
+        file = Tempfile.open([ "ActiveStorage", tempfile_extension_with_delimiter ], tempdir)
 
         begin
           yield file
diff --git a/activestorage/lib/active_storage/previewer.rb b/activestorage/lib/active_storage/previewer.rb
index f09dc25879..bff5e42d41 100644
--- a/activestorage/lib/active_storage/previewer.rb
+++ b/activestorage/lib/active_storage/previewer.rb
@@ -26,7 +26,7 @@ module ActiveStorage
     private
       # Downloads the blob to a tempfile on disk. Yields the tempfile.
       def download_blob_to_tempfile(&block) #:doc:
-        blob.open(&block)
+        blob.open tempdir: tempdir, &block
       end
 
       # Executes a system command, capturing its binary output in a tempfile. Yields the tempfile.
diff --git a/activestorage/test/models/blob_test.rb b/activestorage/test/models/blob_test.rb
index 1bc5951d79..a013b7a924 100644
--- a/activestorage/test/models/blob_test.rb
+++ b/activestorage/test/models/blob_test.rb
@@ -93,6 +93,18 @@ class ActiveStorage::BlobTest < ActiveSupport::TestCase
     end
   end
 
+  test "open in a custom tempdir" do
+    tempdir = Dir.mktmpdir
+
+    create_file_blob(filename: "racecar.jpg").open(tempdir: tempdir) do |file|
+      assert file.binmode?
+      assert_equal 0, file.pos
+      assert_match(/\.jpg\z/, file.path)
+      assert file.path.starts_with?(tempdir)
+      assert_equal file_fixture("racecar.jpg").binread, file.read, "Expected downloaded file to match fixture file"
+    end
+  end
+
   test "urls expiring in 5 minutes" do
     blob = create_blob
 
-- 
cgit v1.2.3