Skip to content
This repository
Browse code

Allow for URI Adapter as an optional paperclip io adapter

This PR allows you to assign a URI object to an attachment. The
attachment is downloaded and saved with a proper content type and
filename based on the path of the URL.
  • Loading branch information...
commit 5d06ad8c570354db59d067613b04841833252a8d 1 parent 786a13f
Aditya Sanghi authored July 20, 2012 jyurek committed July 20, 2012
1  lib/paperclip.rb
@@ -223,3 +223,4 @@ def attachment_definitions
223 223
 require 'paperclip/io_adapters/nil_adapter'
224 224
 require 'paperclip/io_adapters/attachment_adapter'
225 225
 require 'paperclip/io_adapters/uploaded_file_adapter'
  226
+require 'paperclip/io_adapters/uri_adapter'
42  lib/paperclip/io_adapters/uri_adapter.rb
... ...
@@ -0,0 +1,42 @@
  1
+require 'open-uri'
  2
+
  3
+module Paperclip
  4
+  class UriAdapter < AbstractAdapter
  5
+    def initialize(target)
  6
+      @target = target
  7
+      @content = download_content
  8
+      cache_current_values
  9
+      @tempfile = copy_to_tempfile(@content)
  10
+    end
  11
+
  12
+    attr_writer :original_filename, :content_type
  13
+    private
  14
+
  15
+    def download_content
  16
+      open(@target)
  17
+    end
  18
+
  19
+    def cache_current_values
  20
+      @original_filename = @target.path.split("/").last
  21
+      @original_filename ||= "index.html"
  22
+      @original_filename = @original_filename.strip
  23
+
  24
+      @content_type = @content.content_type if @content.respond_to?(:content_type)
  25
+      @content_type ||= "text/html"
  26
+
  27
+      @size = @content.size
  28
+    end
  29
+
  30
+    def copy_to_tempfile(src)
  31
+      while data = src.read(16*1024)
  32
+        destination.write(data)
  33
+      end
  34
+      destination.rewind
  35
+      destination
  36
+    end
  37
+  end
  38
+end
  39
+
  40
+Paperclip.io_adapters.register Paperclip::UriAdapter do |target|
  41
+  target.kind_of?(URI)
  42
+end
14  test/io_adapters/attachment_adapter_test.rb
... ...
@@ -1,12 +1,12 @@
1 1
 require './test/helper'
2 2
 
3 3
 class AttachmentAdapterTest < Test::Unit::TestCase
4  
-  
  4
+
5 5
   def setup
6 6
     rebuild_model :path => "tmp/:class/:attachment/:style/:filename", :styles => {:thumb => '50x50'}
7 7
     @attachment = Dummy.new.avatar
8 8
   end
9  
-  
  9
+
10 10
   context "for an attachment" do
11 11
     setup do
12 12
       @file = File.new(fixture_file("5k.png"))
@@ -53,19 +53,19 @@ def setup
53 53
       assert_equal expected.length, actual.length
54 54
       assert_equal expected, actual
55 55
     end
56  
-    
  56
+
57 57
   end
58  
-  
  58
+
59 59
   context "for a style" do
60 60
     setup do
61 61
       @file = File.new(fixture_file("5k.png"))
62 62
       @file.binmode
63 63
 
64 64
       @attachment.assign(@file)
65  
-    
  65
+
66 66
       @thumb = Tempfile.new("thumbnail").tap(&:binmode)
67 67
       FileUtils.cp @attachment.queued_for_write[:thumb].path, @thumb.path
68  
-    
  68
+
69 69
       @attachment.save
70 70
       @subject = Paperclip.io_adapters.for(@attachment.styles[:thumb])
71 71
     end
@@ -108,6 +108,6 @@ def setup
108 108
       assert_equal expected.length, actual.length
109 109
       assert_equal expected, actual
110 110
     end
111  
-    
  111
+
112 112
   end
113 113
 end
6  test/io_adapters/stringio_adapter_test.rb
@@ -36,16 +36,16 @@ class StringioFileProxyTest < Test::Unit::TestCase
36 36
     should "return the data contained in the StringIO" do
37 37
       assert_equal "abc123", @subject.read
38 38
     end
39  
-    
  39
+
40 40
     should 'accept a content_type' do
41 41
       @subject.content_type = 'image/png'
42 42
       assert_equal 'image/png', @subject.content_type
43 43
     end
44  
-    
  44
+
45 45
     should 'accept an orgiginal_filename' do
46 46
       @subject.original_filename = 'image.png'
47 47
       assert_equal 'image.png', @subject.original_filename
48 48
     end
49  
-    
  49
+
50 50
   end
51 51
 end
82  test/io_adapters/uri_adapter_test.rb
... ...
@@ -0,0 +1,82 @@
  1
+require './test/helper'
  2
+
  3
+class UriProxyTest < Test::Unit::TestCase
  4
+  context "a new instance" do
  5
+    setup do
  6
+      @open_return = StringIO.new("xxx")
  7
+      @open_return.stubs(:content_type).returns("image/png")
  8
+      Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(@open_return)
  9
+      @uri = URI.parse("http://thoughtbot.com/images/thoughtbot-logo.png")
  10
+      @subject = Paperclip.io_adapters.for(@uri)
  11
+    end
  12
+
  13
+    should "return a file name" do
  14
+      assert_equal "thoughtbot-logo.png", @subject.original_filename
  15
+    end
  16
+
  17
+    should "return a content type" do
  18
+      assert_equal "image/png", @subject.content_type
  19
+    end
  20
+
  21
+    should "return the size of the data" do
  22
+      assert_equal @open_return.size, @subject.size
  23
+    end
  24
+
  25
+    should "generate an MD5 hash of the contents" do
  26
+      assert_equal Digest::MD5.hexdigest("xxx"), @subject.fingerprint
  27
+    end
  28
+
  29
+    should "generate correct fingerprint after read" do
  30
+      fingerprint = Digest::MD5.hexdigest(@subject.read)
  31
+      assert_equal fingerprint, @subject.fingerprint
  32
+    end
  33
+
  34
+    should "generate same fingerprint" do
  35
+      assert_equal @subject.fingerprint, @subject.fingerprint
  36
+    end
  37
+
  38
+    should "return the data contained in the StringIO" do
  39
+      assert_equal "xxx", @subject.read
  40
+    end
  41
+
  42
+    should 'accept a content_type' do
  43
+      @subject.content_type = 'image/png'
  44
+      assert_equal 'image/png', @subject.content_type
  45
+    end
  46
+
  47
+    should 'accept an orgiginal_filename' do
  48
+      @subject.original_filename = 'image.png'
  49
+      assert_equal 'image.png', @subject.original_filename
  50
+    end
  51
+
  52
+  end
  53
+
  54
+  context "a directory index url" do
  55
+    setup do
  56
+      Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
  57
+      @uri = URI.parse("http://thoughtbot.com")
  58
+      @subject = Paperclip.io_adapters.for(@uri)
  59
+    end
  60
+
  61
+    should "return a file name" do
  62
+      assert_equal "index.html", @subject.original_filename
  63
+    end
  64
+
  65
+    should "return a content type" do
  66
+      assert_equal "text/html", @subject.content_type
  67
+    end
  68
+  end
  69
+
  70
+  context "a url with query params" do
  71
+    setup do
  72
+      Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
  73
+      @uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
  74
+      @subject = Paperclip.io_adapters.for(@uri)
  75
+    end
  76
+
  77
+    should "return a file name" do
  78
+      assert_equal "paperclip", @subject.original_filename
  79
+    end
  80
+  end
  81
+
  82
+end

0 notes on commit 5d06ad8

Please sign in to comment.
Something went wrong with that request. Please try again.