Skip to content

Commit

Permalink
Refactor shared behavior into AbstractAdapter superclass
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Yurek committed Jun 15, 2012
1 parent 6728166 commit 49b833a
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 162 deletions.
43 changes: 41 additions & 2 deletions 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
Expand All @@ -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
Expand Down
37 changes: 0 additions & 37 deletions lib/paperclip/io_adapters/attachment_adapter.rb
Expand Up @@ -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
Expand Down
47 changes: 10 additions & 37 deletions lib/paperclip/io_adapters/file_adapter.rb
Expand Up @@ -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
Expand All @@ -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

Expand Down
46 changes: 7 additions & 39 deletions lib/paperclip/io_adapters/stringio_adapter.rb
Expand Up @@ -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)
Expand Down
40 changes: 6 additions & 34 deletions lib/paperclip/io_adapters/uploaded_file_adapter.rb
Expand Up @@ -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)
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions lib/paperclip/storage/filesystem.rb
Expand Up @@ -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
2 changes: 2 additions & 0 deletions test/io_adapters/file_adapter_test.rb
Expand Up @@ -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
Expand All @@ -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
Expand Down
10 changes: 0 additions & 10 deletions test/io_adapters/stringio_adapter_test.rb
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion test/io_adapters/uploaded_file_adapter_test.rb
Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions test/storage/s3_test.rb
Expand Up @@ -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
Expand Down

0 comments on commit 49b833a

Please sign in to comment.