From 49b833a48acd33cca1264ec67f4ede3cfa06081d Mon Sep 17 00:00:00 2001 From: Jon Yurek Date: Fri, 15 Jun 2012 11:40:05 -0400 Subject: [PATCH] Refactor shared behavior into AbstractAdapter superclass --- lib/paperclip/io_adapters/abstract_adapter.rb | 43 ++++++++++++++++- .../io_adapters/attachment_adapter.rb | 37 --------------- lib/paperclip/io_adapters/file_adapter.rb | 47 ++++--------------- lib/paperclip/io_adapters/stringio_adapter.rb | 46 +++--------------- .../io_adapters/uploaded_file_adapter.rb | 40 +++------------- lib/paperclip/storage/filesystem.rb | 4 ++ test/io_adapters/file_adapter_test.rb | 2 + test/io_adapters/stringio_adapter_test.rb | 10 ---- .../io_adapters/uploaded_file_adapter_test.rb | 3 +- test/storage/s3_test.rb | 9 +++- 10 files changed, 79 insertions(+), 162 deletions(-) diff --git a/lib/paperclip/io_adapters/abstract_adapter.rb b/lib/paperclip/io_adapters/abstract_adapter.rb index 736f76784..5dc430c66 100644 --- a/lib/paperclip/io_adapters/abstract_adapter.rb +++ b/lib/paperclip/io_adapters/abstract_adapter.rb @@ -1,5 +1,43 @@ module Paperclip class AbstractAdapter + + def original_filename + @original_filename + end + + def content_type + @content_type + end + + def size + @size + end + + def fingerprint + @fingerprint ||= Digest::MD5.file(path).to_s + end + + def nil? + false + end + + def read(length = nil, buffer = nil) + @tempfile.read(length, buffer) + end + + # We don't use this directly, but aws/sdk does. + def rewind + @tempfile.rewind + end + + def eof? + @tempfile.eof? + end + + def path + @tempfile.path + end + private def destination @@ -22,8 +60,9 @@ def best_content_type_option(types) def type_from_file_command # On BSDs, `file` doesn't give a result code of 1 if the file doesn't exist. - type = (self.original_filename.match(/\.(\w+)$/)[1] rescue "octet-stream").downcase - mime_type = (Paperclip.run("file", "-b --mime :file", :file => self.path).split(/[:;\s]+/)[0] rescue "application/x-#{type}") + type = (File.extname(self.path.to_s)).downcase + type = "octet-stream" if type.empty? + mime_type = Paperclip.run("file", "-b --mime :file", :file => self.path).split(/[:;\s]+/)[0] mime_type = "application/x-#{type}" if mime_type.match(/\(.*?\)/) mime_type end diff --git a/lib/paperclip/io_adapters/attachment_adapter.rb b/lib/paperclip/io_adapters/attachment_adapter.rb index 0e970027a..17c8c5e5c 100644 --- a/lib/paperclip/io_adapters/attachment_adapter.rb +++ b/lib/paperclip/io_adapters/attachment_adapter.rb @@ -11,43 +11,6 @@ def initialize(target) cache_current_values end - def original_filename - @original_filename - end - - def content_type - @content_type - end - - def size - @size - end - - def nil? - false - end - - def fingerprint - @fingerprint ||= Digest::MD5.file(path).to_s - end - - def read(length = nil, buffer = nil) - @tempfile.read(length, buffer) - end - - # We don't use this directly, but aws/sdk does. - def rewind - @tempfile.rewind - end - - def eof? - @tempfile.eof? - end - - def path - @tempfile.path - end - private def cache_current_values diff --git a/lib/paperclip/io_adapters/file_adapter.rb b/lib/paperclip/io_adapters/file_adapter.rb index cf582164c..8284c5326 100644 --- a/lib/paperclip/io_adapters/file_adapter.rb +++ b/lib/paperclip/io_adapters/file_adapter.rb @@ -2,18 +2,20 @@ module Paperclip class FileAdapter < AbstractAdapter def initialize(target) @target = target - @tempfile = copy_to_tempfile(@target) + cache_current_values end - def original_filename - if @target.respond_to?(:original_filename) - @target.original_filename - else - File.basename(@target.path) - end + private + + def cache_current_values + @original_filename = @target.original_filename if @target.respond_to?(:original_filename) + @original_filename ||= File.basename(@target.path) + @tempfile = copy_to_tempfile(@target) + @content_type = calculate_content_type + @size = File.size(@target) end - def content_type + def calculate_content_type types = MIME::Types.type_for(original_filename) if types.length == 0 type_from_file_command @@ -23,35 +25,6 @@ def content_type best_content_type_option(types) end end - - def fingerprint - @fingerprint ||= Digest::MD5.file(path).to_s - end - - def size - File.size(@tempfile) - end - - def nil? - @target.nil? - end - - def read(length = nil, buffer = nil) - @tempfile.read(length, buffer) - end - - # We don't use this directly, but aws/sdk does. - def rewind - @tempfile.rewind - end - - def eof? - @tempfile.eof? - end - - def path - @tempfile.path - end end end diff --git a/lib/paperclip/io_adapters/stringio_adapter.rb b/lib/paperclip/io_adapters/stringio_adapter.rb index f45f1666e..49260a3e5 100644 --- a/lib/paperclip/io_adapters/stringio_adapter.rb +++ b/lib/paperclip/io_adapters/stringio_adapter.rb @@ -2,55 +2,23 @@ module Paperclip class StringioAdapter < AbstractAdapter def initialize(target) @target = target + cache_current_values @tempfile = copy_to_tempfile(@target) end - attr_writer :original_filename, :content_type + private - def original_filename - @original_filename ||= @target.original_filename if @target.respond_to?(:original_filename) + def cache_current_values + @original_filename = @target.original_filename if @target.respond_to?(:original_filename) @original_filename ||= "stringio.txt" - @original_filename.strip - end + @original_filename = @original_filename.strip - def content_type - @content_type ||= @target.content_type if @target.respond_to?(:content_type) + @content_type = @target.content_type if @target.respond_to?(:content_type) @content_type ||= "text/plain" - @content_type - end - - def size - @target.size - end - - def fingerprint - if (@cached_fingerprint.nil?) - rewind # start reading from the beginning - @cached_fingerprint = Digest::MD5.hexdigest(read) - rewind # for later read() - end - @cached_fingerprint - end - def read(length = nil, buffer = nil) - @tempfile.read(length, buffer) + @size = @target.size end - # We don't use this directly, but aws/sdk does. - def rewind - @tempfile.rewind - end - - def eof? - @tempfile.eof? - end - - def path - @tempfile.path - end - - private - def copy_to_tempfile(src) while data = src.read(16*1024) destination.write(data) diff --git a/lib/paperclip/io_adapters/uploaded_file_adapter.rb b/lib/paperclip/io_adapters/uploaded_file_adapter.rb index 05bb58d2f..84d9418af 100644 --- a/lib/paperclip/io_adapters/uploaded_file_adapter.rb +++ b/lib/paperclip/io_adapters/uploaded_file_adapter.rb @@ -2,6 +2,7 @@ module Paperclip class UploadedFileAdapter < AbstractAdapter def initialize(target) @target = target + cache_current_values if @target.respond_to?(:tempfile) @tempfile = copy_to_tempfile(@target.tempfile) @@ -10,41 +11,12 @@ def initialize(target) end end - def original_filename - @target.original_filename - end - - def content_type - @target.content_type - end - - def fingerprint - @fingerprint ||= Digest::MD5.file(path).to_s - end - - def size - File.size(path) - end - - def nil? - false - end - - def read(length = nil, buffer = nil) - @tempfile.read(length, buffer) - end - - # We don't use this directly, but aws/sdk does. - def rewind - @tempfile.rewind - end - - def eof? - @tempfile.eof? - end + private - def path - @tempfile.path + def cache_current_values + @original_filename = @target.original_filename + @content_type = @target.content_type + @size = File.size(@target.path) end end end diff --git a/lib/paperclip/storage/filesystem.rb b/lib/paperclip/storage/filesystem.rb index 7ae9c39e2..78d6650d7 100644 --- a/lib/paperclip/storage/filesystem.rb +++ b/lib/paperclip/storage/filesystem.rb @@ -68,5 +68,9 @@ def flush_deletes #:nodoc: end end + def copy_to_local_file(style, local_dest_path) + FileUtils.cp(path(style), local_dest_path) + end + end end diff --git a/test/io_adapters/file_adapter_test.rb b/test/io_adapters/file_adapter_test.rb index 60b1af676..1f44629bf 100644 --- a/test/io_adapters/file_adapter_test.rb +++ b/test/io_adapters/file_adapter_test.rb @@ -63,6 +63,7 @@ class FileAdapterTest < Test::Unit::TestCase context "file with multiple possible x-types but no official type" do setup do MIME::Types.stubs(:type_for).returns([MIME::Type.new('image/x-mp4'), MIME::Type.new('image/x-video')]) + @subject = Paperclip.io_adapters.for(@file) end should "return the first" do @@ -74,6 +75,7 @@ class FileAdapterTest < Test::Unit::TestCase setup do MIME::Types.stubs(:type_for).returns([]) Paperclip.stubs(:run).returns("application/vnd.ms-office\n") + @subject = Paperclip.io_adapters.for(@file) end should "return content type without newline character" do diff --git a/test/io_adapters/stringio_adapter_test.rb b/test/io_adapters/stringio_adapter_test.rb index 43567bfb6..3eba9565b 100644 --- a/test/io_adapters/stringio_adapter_test.rb +++ b/test/io_adapters/stringio_adapter_test.rb @@ -12,20 +12,10 @@ class StringioFileProxyTest < Test::Unit::TestCase assert_equal "stringio.txt", @subject.original_filename end - should "allow us to set a name" do - @subject.original_filename = "data.txt" - assert_equal "data.txt", @subject.original_filename - end - should "return a content type" do assert_equal "text/plain", @subject.content_type end - should "allow us to set a content type" do - @subject.content_type = "image/jpg" - assert_equal "image/jpg", @subject.content_type - end - should "return the size of the data" do assert_equal 6, @subject.size end diff --git a/test/io_adapters/uploaded_file_adapter_test.rb b/test/io_adapters/uploaded_file_adapter_test.rb index 0d120f433..7660ef966 100644 --- a/test/io_adapters/uploaded_file_adapter_test.rb +++ b/test/io_adapters/uploaded_file_adapter_test.rb @@ -12,7 +12,8 @@ class UploadedFile < OpenStruct; end :original_filename => "5k.png", :content_type => "image/png", :head => "", - :tempfile => tempfile + :tempfile => tempfile, + :path => tempfile.path ) @subject = Paperclip.io_adapters.for(@file) end diff --git a/test/storage/s3_test.rb b/test/storage/s3_test.rb index db1099d12..23c2f68d4 100644 --- a/test/storage/s3_test.rb +++ b/test/storage/s3_test.rb @@ -276,8 +276,13 @@ def teardown 'secret_access_key' => "54321" } - file = Paperclip.io_adapters.for(StringIO.new(".")) - file.original_filename = "question?mark.png" + stringio = StringIO.new(".") + class << stringio + def original_filename + "question?mark.png" + end + end + file = Paperclip.io_adapters.for(stringio) @dummy = Dummy.new @dummy.avatar = file @dummy.save