joshpuetz-paperclip 2.3.0.1 → 2.3.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/paperclip.rb CHANGED
@@ -44,7 +44,7 @@ end
44
44
  # documentation for Paperclip::ClassMethods for more useful information.
45
45
  module Paperclip
46
46
 
47
- VERSION = "2.2.9.2"
47
+ VERSION = "2.3.0"
48
48
 
49
49
  class << self
50
50
  # Provides configurability to Paperclip. There are a number of options available, such as:
@@ -93,7 +93,7 @@ module Paperclip
93
93
  # Paperclip.options[:log_command] is set to true (defaults to false). This
94
94
  # will only log if logging in general is set to true as well.
95
95
  def run cmd, params = "", expected_outcodes = 0
96
- command = %Q<#{%Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ")}>
96
+ command = %Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ")
97
97
  command = "#{command} 2>#{bit_bucket}" if Paperclip.options[:swallow_stderr]
98
98
  Paperclip.log(command) if Paperclip.options[:log_command]
99
99
  output = `#{command}`
@@ -189,6 +189,9 @@ module Paperclip
189
189
  # to a command line error. This will override the global setting for this attachment.
190
190
  # Defaults to true. This option used to be called :whiny_thumbanils, but this is
191
191
  # deprecated.
192
+ # * +keep_old_files+: Keep the existing attachment files (original + resized) from
193
+ # being automatically deleted when an attachment is cleared or updated.
194
+ # Defaults to +false+.
192
195
  # * +convert_options+: When creating thumbnails, use this free-form options
193
196
  # field to pass in various convert command options. Typical options are "-strip" to
194
197
  # remove all Exif data from the image (save space for thumbnails and avatars) or
@@ -14,7 +14,8 @@ module Paperclip
14
14
  :default_style => :original,
15
15
  :validations => [],
16
16
  :storage => :filesystem,
17
- :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails]
17
+ :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails],
18
+ :keep_old_files=> false
18
19
  }
19
20
  end
20
21
 
@@ -40,6 +41,7 @@ module Paperclip
40
41
  @default_style = options[:default_style]
41
42
  @storage = options[:storage]
42
43
  @whiny = options[:whiny_thumbnails] || options[:whiny]
44
+ @keep_old_files = options[:keep_old_files]
43
45
  @convert_options = options[:convert_options] || {}
44
46
  @processors = options[:processors] || [:thumbnail]
45
47
  @options = options
@@ -394,9 +396,11 @@ module Paperclip
394
396
 
395
397
  def queue_existing_for_delete #:nodoc:
396
398
  return unless file?
397
- @queued_for_delete += [:original, *@styles.keys].uniq.map do |style|
398
- path(style) if exists?(style)
399
- end.compact
399
+ unless @keep_old_files
400
+ @queued_for_delete += [:original, *@styles.keys].uniq.map do |style|
401
+ path(style) if exists?(style)
402
+ end.compact
403
+ end
400
404
  instance_write(:file_name, nil)
401
405
  instance_write(:content_type, nil)
402
406
  instance_write(:file_size, nil)
@@ -33,7 +33,6 @@ module Paperclip
33
33
  def to_file style = default_style
34
34
  @queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style))
35
35
  end
36
- alias_method :to_io, :to_file
37
36
 
38
37
  def flush_writes #:nodoc:
39
38
  @queued_for_write.each do |style, file|
@@ -128,17 +127,21 @@ module Paperclip
128
127
  # separate parts of your file name.
129
128
  module S3
130
129
  def self.extended base
131
- require 'right_aws'
130
+ require 'aws/s3'
132
131
  base.instance_eval do
133
132
  @s3_credentials = parse_credentials(@options[:s3_credentials])
134
133
  @bucket = @options[:bucket] || @s3_credentials[:bucket]
135
134
  @bucket = @bucket.call(self) if @bucket.is_a?(Proc)
136
135
  @s3_options = @options[:s3_options] || {}
137
- @s3_permissions = @options[:s3_permissions] || 'public-read'
138
- @s3_protocol = @options[:s3_protocol] || (@s3_permissions == 'public-read' ? 'http' : 'https')
136
+ @s3_permissions = @options[:s3_permissions] || :public_read
137
+ @s3_protocol = @options[:s3_protocol] || (@s3_permissions == :public_read ? 'http' : 'https')
139
138
  @s3_headers = @options[:s3_headers] || {}
140
139
  @s3_host_alias = @options[:s3_host_alias]
141
140
  @url = ":s3_path_url" unless @url.to_s.match(/^:s3.*url$/)
141
+ AWS::S3::Base.establish_connection!( @s3_options.merge(
142
+ :access_key_id => @s3_credentials[:access_key_id],
143
+ :secret_access_key => @s3_credentials[:secret_access_key]
144
+ ))
142
145
  end
143
146
  Paperclip.interpolates(:s3_alias_url) do |attachment, style|
144
147
  "#{attachment.s3_protocol}://#{attachment.s3_host_alias}/#{attachment.path(style).gsub(%r{^/}, "")}"
@@ -151,16 +154,6 @@ module Paperclip
151
154
  end
152
155
  end
153
156
 
154
- def s3
155
- @s3 ||= RightAws::S3.new(@s3_credentials[:access_key_id],
156
- @s3_credentials[:secret_access_key],
157
- @s3_options)
158
- end
159
-
160
- def s3_bucket
161
- @s3_bucket ||= s3.bucket(@bucket, true, @s3_permissions)
162
- end
163
-
164
157
  def bucket_name
165
158
  @bucket
166
159
  end
@@ -175,7 +168,11 @@ module Paperclip
175
168
  end
176
169
 
177
170
  def exists?(style = default_style)
178
- s3_bucket.key(path(style)) ? true : false
171
+ if original_filename
172
+ AWS::S3::S3Object.exists?(path(style), bucket_name)
173
+ else
174
+ false
175
+ end
179
176
  end
180
177
 
181
178
  def s3_protocol
@@ -185,18 +182,24 @@ module Paperclip
185
182
  # Returns representation of the data of the file assigned to the given
186
183
  # style, in the format most representative of the current storage.
187
184
  def to_file style = default_style
188
- @queued_for_write[style] || s3_bucket.key(path(style))
185
+ return @queued_for_write[style] if @queued_for_write[style]
186
+ file = Tempfile.new(path(style))
187
+ file.write(AWS::S3::S3Object.value(path(style), bucket_name))
188
+ file.rewind
189
+ return file
189
190
  end
190
- alias_method :to_io, :to_file
191
191
 
192
192
  def flush_writes #:nodoc:
193
193
  @queued_for_write.each do |style, file|
194
194
  begin
195
195
  log("saving #{path(style)}")
196
- key = s3_bucket.key(path(style))
197
- key.data = file
198
- key.put(nil, @s3_permissions, {'Content-type' => instance_read(:content_type)}.merge(@s3_headers))
199
- rescue RightAws::AwsError => e
196
+ AWS::S3::S3Object.store(path(style),
197
+ file,
198
+ bucket_name,
199
+ {:content_type => instance_read(:content_type),
200
+ :access => @s3_permissions,
201
+ }.merge(@s3_headers))
202
+ rescue AWS::S3::ResponseError => e
200
203
  raise
201
204
  end
202
205
  end
@@ -207,10 +210,8 @@ module Paperclip
207
210
  @queued_for_delete.each do |path|
208
211
  begin
209
212
  log("deleting #{path}")
210
- if file = s3_bucket.key(path)
211
- file.delete
212
- end
213
- rescue RightAws::AwsError
213
+ AWS::S3::S3Object.delete(path, bucket_name)
214
+ rescue AWS::S3::ResponseError
214
215
  # Ignore this.
215
216
  end
216
217
  end
@@ -2,7 +2,7 @@ module Paperclip
2
2
  # Handles thumbnailing images that are uploaded.
3
3
  class Thumbnail < Processor
4
4
 
5
- attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options
5
+ attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options, :source_file_options
6
6
 
7
7
  # Creates a Thumbnail object set to work on the +file+ given. It
8
8
  # will attempt to transform the image into one defined by +target_geometry+
@@ -12,17 +12,18 @@ module Paperclip
12
12
  # set, the options will be appended to the convert command upon image conversion
13
13
  def initialize file, options = {}, attachment = nil
14
14
  super
15
- geometry = options[:geometry]
16
- @file = file
17
- @crop = geometry[-1,1] == '#'
18
- @target_geometry = Geometry.parse geometry
19
- @current_geometry = Geometry.from_file @file
20
- @convert_options = options[:convert_options]
21
- @whiny = options[:whiny].nil? ? true : options[:whiny]
22
- @format = options[:format]
15
+ geometry = options[:geometry]
16
+ @file = file
17
+ @crop = geometry[-1,1] == '#'
18
+ @target_geometry = Geometry.parse geometry
19
+ @current_geometry = Geometry.from_file @file
20
+ @source_file_options = options[:source_file_options]
21
+ @convert_options = options[:convert_options]
22
+ @whiny = options[:whiny].nil? ? true : options[:whiny]
23
+ @format = options[:format]
23
24
 
24
- @current_format = File.extname(@file.path)
25
- @basename = File.basename(@file.path, @current_format)
25
+ @current_format = File.extname(@file.path)
26
+ @basename = File.basename(@file.path, @current_format)
26
27
  end
27
28
 
28
29
  # Returns true if the +target_geometry+ is meant to crop.
@@ -43,6 +44,7 @@ module Paperclip
43
44
  dst.binmode
44
45
 
45
46
  command = <<-end_command
47
+ #{ source_file_options }
46
48
  "#{ File.expand_path(src.path) }[0]"
47
49
  #{ transformation_command }
48
50
  "#{ File.expand_path(dst.path) }"
@@ -61,7 +63,8 @@ module Paperclip
61
63
  # into the thumbnail.
62
64
  def transformation_command
63
65
  scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
64
- trans = "-resize \"#{scale}\""
66
+ trans = ""
67
+ trans << " -resize \"#{scale}\"" unless scale.blank?
65
68
  trans << " -crop \"#{crop}\" +repage" if crop
66
69
  trans << " #{convert_options}" if convert_options?
67
70
  trans
@@ -14,14 +14,27 @@ class AttachmentTest < Test::Unit::TestCase
14
14
  assert_equal "#{RAILS_ROOT}/public/fake_models/1234/fake", @attachment.path
15
15
  end
16
16
 
17
+ should "call a proc sent to check_guard" do
18
+ @dummy = Dummy.new
19
+ @dummy.expects(:one).returns(:one)
20
+ assert_equal :one, @dummy.avatar.send(:check_guard, lambda{|x| x.one })
21
+ end
22
+
23
+ should "call a method name sent to check_guard" do
24
+ @dummy = Dummy.new
25
+ @dummy.expects(:one).returns(:one)
26
+ assert_equal :one, @dummy.avatar.send(:check_guard, :one)
27
+ end
28
+
17
29
  context "Attachment default_options" do
18
30
  setup do
19
31
  rebuild_model
20
32
  @old_default_options = Paperclip::Attachment.default_options.dup
21
33
  @new_default_options = @old_default_options.merge({
22
- :path => "argle/bargle",
23
- :url => "fooferon",
24
- :default_url => "not here.png"
34
+ :path => "argle/bargle",
35
+ :url => "fooferon",
36
+ :default_url => "not here.png",
37
+ :keep_old_files => false
25
38
  })
26
39
  end
27
40
 
@@ -592,7 +605,7 @@ class AttachmentTest < Test::Unit::TestCase
592
605
 
593
606
  should "commit the files to disk" do
594
607
  [:large, :medium, :small].each do |style|
595
- io = @attachment.to_io(style)
608
+ io = @attachment.to_file(style)
596
609
  assert File.exists?(io)
597
610
  assert ! io.is_a?(::Tempfile)
598
611
  io.close
@@ -764,4 +777,94 @@ class AttachmentTest < Test::Unit::TestCase
764
777
  end
765
778
  end
766
779
  end
780
+
781
+
782
+ ######################
783
+ # test :keep_old_files
784
+ ######################
785
+
786
+ context "An attachment with :keep_old_files => true" do
787
+
788
+ setup do
789
+ @old_defaults = Paperclip::Attachment.default_options.dup
790
+ Paperclip::Attachment.default_options.merge!( {
791
+ :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
792
+ })
793
+ FileUtils.rm_rf("tmp")
794
+
795
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png" ), 'rb')
796
+ @file_2 = File.new(File.join(File.dirname(__FILE__), "fixtures", "50x50.png"), 'rb')
797
+
798
+ rebuild_model
799
+ @instance = Dummy.new
800
+
801
+ @attachment = Paperclip::Attachment.new(:avatar, @instance, {
802
+ :keep_old_files => true,
803
+ :styles => {:small => "32x32#"}
804
+ })
805
+ @attachment.assign(@file)
806
+ @attachment.save
807
+ end
808
+
809
+ teardown do
810
+ @file.close
811
+ @file_2.close
812
+ Paperclip::Attachment.default_options.merge!(@old_defaults)
813
+ end
814
+
815
+ should "return the real urls" do
816
+ assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
817
+ assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.png} , @attachment.url(:small)
818
+ end
819
+
820
+ should "commit the files to disk" do
821
+ assert File.exists?(@attachment.path(:original))
822
+ assert File.exists?(@attachment.path(:small ))
823
+ end
824
+
825
+
826
+ context "after assigning a new file" do
827
+ setup do
828
+ @previous_files_path = @attachment.styles.keys.collect do |style|
829
+ @attachment.path(style)
830
+ end
831
+ @attachment.assign @file_2
832
+ @attachment.save
833
+ end
834
+
835
+ should "NOT delete the previous files after assigning nil and saving" do
836
+ @previous_files_path.each{|f| assert File.exists?(f), "#{f} should NOT have been deleted" }
837
+ end
838
+ end
839
+
840
+
841
+ context "" do
842
+ setup do
843
+ @old_files_path = @attachment.styles.keys.collect do |style|
844
+ @attachment.path(style)
845
+ end
846
+ end
847
+
848
+ should "NOT delete the files after assigning nil and saving" do
849
+ @attachment.expects_instance_write_with_nil___in_the_4_paperclip_columns
850
+ @attachment.assign nil
851
+ @attachment.save
852
+ @old_files_path.each{|f| assert File.exists?(f), "#{f} should NOT have been deleted" }
853
+ end
854
+
855
+ should "NOT delete the files when you call #clear and #save" do
856
+ @attachment.expects_instance_write_with_nil___in_the_4_paperclip_columns
857
+ @attachment.clear
858
+ @attachment.save
859
+ @old_files_path.each{|f| assert File.exists?(f), "#{f} should NOT have been deleted" }
860
+ end
861
+
862
+ should "NOT delete the files when you call #delete" do
863
+ @attachment.expects_instance_write_with_nil___in_the_4_paperclip_columns
864
+ @attachment.destroy
865
+ @old_files_path.each{|f| assert File.exists?(f), "#{f} should NOT have been deleted" }
866
+ end
867
+ end
868
+
869
+ end
767
870
  end
data/test/helper.rb CHANGED
@@ -97,3 +97,14 @@ end
97
97
  def attachment options
98
98
  Paperclip::Attachment.new(:avatar, FakeModel.new, options)
99
99
  end
100
+
101
+ module Paperclip
102
+ class Attachment
103
+ def expects_instance_write_with_nil___in_the_4_paperclip_columns
104
+ expects(:instance_write).with(:file_name , nil)
105
+ expects(:instance_write).with(:content_type , nil)
106
+ expects(:instance_write).with(:file_size , nil)
107
+ expects(:instance_write).with(:updated_at , nil)
108
+ end
109
+ end
110
+ end
@@ -379,6 +379,11 @@ class IntegrationTest < Test::Unit::TestCase
379
379
  @files_on_s3 = s3_files_for @dummy.avatar
380
380
  end
381
381
 
382
+ should "have the same contents as the original" do
383
+ @file.rewind
384
+ assert_equal @file.read, @files_on_s3[:original].read
385
+ end
386
+
382
387
  should "write and delete its files" do
383
388
  [["434x66", :original],
384
389
  ["300x46", :large],
@@ -403,10 +408,8 @@ class IntegrationTest < Test::Unit::TestCase
403
408
  assert @dummy.valid?
404
409
  assert @dummy.save
405
410
 
406
- saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
407
-
408
- saved_keys.each do |key|
409
- assert key.exists?
411
+ [:thumb, :medium, :large, :original].each do |style|
412
+ assert @dummy.avatar.exists?(style)
410
413
  end
411
414
 
412
415
  @dummy.avatar.clear
@@ -414,8 +417,8 @@ class IntegrationTest < Test::Unit::TestCase
414
417
  assert @dummy.valid?
415
418
  assert @dummy.save
416
419
 
417
- saved_keys.each do |key|
418
- assert ! key.exists?
420
+ [:thumb, :medium, :large, :original].each do |style|
421
+ assert ! @dummy.avatar.exists?(style)
419
422
  end
420
423
 
421
424
  @d2 = Dummy.find(@dummy.id)
@@ -427,7 +430,7 @@ class IntegrationTest < Test::Unit::TestCase
427
430
 
428
431
  assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
429
432
  [:thumb, :medium, :large, :original].each do |style|
430
- assert_equal @dummy.avatar.to_file(style).to_s, @d2.avatar.to_file(style).to_s
433
+ assert_equal @dummy.avatar.to_file(style).read, @d2.avatar.to_file(style).read
431
434
  end
432
435
 
433
436
  saved_keys = [:thumb, :medium, :large, :original].collect{|s| @dummy.avatar.to_file(s) }
@@ -435,8 +438,8 @@ class IntegrationTest < Test::Unit::TestCase
435
438
  @d2.avatar.clear
436
439
  assert @d2.save
437
440
 
438
- saved_keys.each do |key|
439
- assert ! key.exists?
441
+ [:thumb, :medium, :large, :original].each do |style|
442
+ assert ! @dummy.avatar.exists?(style)
440
443
  end
441
444
  end
442
445
 
@@ -444,7 +447,7 @@ class IntegrationTest < Test::Unit::TestCase
444
447
  expected = @dummy.avatar.to_file
445
448
  @dummy.avatar = "not a file"
446
449
  assert @dummy.valid?
447
- assert_equal expected.full_name, @dummy.avatar.to_file.full_name
450
+ assert_equal expected.read, @dummy.avatar.to_file.read
448
451
 
449
452
  @dummy.avatar = @bad_file
450
453
  assert ! @dummy.valid?
@@ -472,7 +475,6 @@ class IntegrationTest < Test::Unit::TestCase
472
475
 
473
476
  should "have the right content type" do
474
477
  headers = s3_headers_for(@dummy.avatar, :original)
475
- p headers
476
478
  assert_equal 'image/png', headers['content-type']
477
479
  end
478
480
  end
@@ -1,14 +1,18 @@
1
1
  require 'test/helper'
2
2
 
3
3
  class PaperclipTest < Test::Unit::TestCase
4
- [:image_magick_path, :convert_path].each do |path|
5
- context "Calling Paperclip.run with an #{path} specified" do
4
+ [:image_magick_path, :command_path].each do |path|
5
+ context "Calling Paperclip.run with #{path} specified" do
6
6
  setup do
7
7
  Paperclip.options[:image_magick_path] = nil
8
- Paperclip.options[:convert_path] = nil
8
+ Paperclip.options[:command_path] = nil
9
9
  Paperclip.options[path] = "/usr/bin"
10
10
  end
11
11
 
12
+ should "return the expected path for path_for_command" do
13
+ assert_equal "/usr/bin/convert", Paperclip.path_for_command("convert")
14
+ end
15
+
12
16
  should "execute the right command" do
13
17
  Paperclip.expects(:path_for_command).with("convert").returns("/usr/bin/convert")
14
18
  Paperclip.expects(:bit_bucket).returns("/dev/null")
@@ -21,7 +25,11 @@ class PaperclipTest < Test::Unit::TestCase
21
25
  context "Calling Paperclip.run with no path specified" do
22
26
  setup do
23
27
  Paperclip.options[:image_magick_path] = nil
24
- Paperclip.options[:convert_path] = nil
28
+ Paperclip.options[:command_path] = nil
29
+ end
30
+
31
+ should "return the expected path fro path_for_command" do
32
+ assert_equal "convert", Paperclip.path_for_command("convert")
25
33
  end
26
34
 
27
35
  should "execute the right command" do
@@ -30,38 +38,38 @@ class PaperclipTest < Test::Unit::TestCase
30
38
  Paperclip.expects(:"`").with("convert one.jpg two.jpg 2>/dev/null")
31
39
  Paperclip.run("convert", "one.jpg two.jpg")
32
40
  end
41
+ end
33
42
 
34
- should "log the command when :log_command is set" do
43
+ context "Calling Paperclip.run and logging" do
44
+ setup do
45
+ Paperclip.options[:image_magick_path] = nil
46
+ Paperclip.options[:command_path] = nil
47
+ Paperclip.stubs(:bit_bucket).returns("/dev/null")
48
+ Paperclip.stubs(:log)
49
+ Paperclip.stubs(:"`").with("this is the command 2>/dev/null")
50
+ end
51
+
52
+ should "log the command when :log_command is true" do
35
53
  Paperclip.options[:log_command] = true
36
- Paperclip.expects(:bit_bucket).returns("/dev/null")
37
- Paperclip.expects(:log).with("this is the command 2>/dev/null")
38
- Paperclip.expects(:"`").with("this is the command 2>/dev/null")
39
54
  Paperclip.run("this","is the command")
55
+ assert_received(Paperclip, :log) do |p|
56
+ p.with("this is the command 2>/dev/null")
57
+ end
58
+ assert_received(Paperclip, :`) do |p|
59
+ p.with("this is the command 2>/dev/null")
60
+ end
40
61
  end
41
- end
42
-
43
- should "raise when sent #processor and the name of a class that exists but isn't a subclass of Processor" do
44
- assert_raises(Paperclip::PaperclipError){ Paperclip.processor(:attachment) }
45
- end
46
62
 
47
- should "raise when sent #processor and the name of a class that doesn't exist" do
48
- assert_raises(NameError){ Paperclip.processor(:boogey_man) }
49
- end
50
-
51
- should "return a class when sent #processor and the name of a class under Paperclip" do
52
- assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
53
- end
54
-
55
- should "call a proc sent to check_guard" do
56
- @dummy = Dummy.new
57
- @dummy.expects(:one).returns(:one)
58
- assert_equal :one, @dummy.avatar.send(:check_guard, lambda{|x| x.one })
59
- end
60
-
61
- should "call a method name sent to check_guard" do
62
- @dummy = Dummy.new
63
- @dummy.expects(:one).returns(:one)
64
- assert_equal :one, @dummy.avatar.send(:check_guard, :one)
63
+ should "not log the command when :log_command is false" do
64
+ Paperclip.options[:log_command] = false
65
+ Paperclip.run("this","is the command")
66
+ assert_received(Paperclip, :log) do |p|
67
+ p.with("this is the command 2>/dev/null").never
68
+ end
69
+ assert_received(Paperclip, :`) do |p|
70
+ p.with("this is the command 2>/dev/null")
71
+ end
72
+ end
65
73
  end
66
74
 
67
75
  context "Paperclip.bit_bucket" do
@@ -86,6 +94,18 @@ class PaperclipTest < Test::Unit::TestCase
86
94
  end
87
95
  end
88
96
 
97
+ should "raise when sent #processor and the name of a class that exists but isn't a subclass of Processor" do
98
+ assert_raises(Paperclip::PaperclipError){ Paperclip.processor(:attachment) }
99
+ end
100
+
101
+ should "raise when sent #processor and the name of a class that doesn't exist" do
102
+ assert_raises(NameError){ Paperclip.processor(:boogey_man) }
103
+ end
104
+
105
+ should "return a class when sent #processor and the name of a class under Paperclip" do
106
+ assert_equal ::Paperclip::Thumbnail, Paperclip.processor(:thumbnail)
107
+ end
108
+
89
109
  context "An ActiveRecord model with an 'avatar' attachment" do
90
110
  setup do
91
111
  rebuild_model :path => "tmp/:class/omg/:style.:extension"
@@ -139,7 +159,8 @@ class PaperclipTest < Test::Unit::TestCase
139
159
  end
140
160
 
141
161
  should "be able to see the attachment definition from the subclass's class" do
142
- assert_equal "tmp/:class/omg/:style.:extension", SubDummy.attachment_definitions[:avatar][:path]
162
+ assert_equal "tmp/:class/omg/:style.:extension",
163
+ SubDummy.attachment_definitions[:avatar][:path]
143
164
  end
144
165
 
145
166
  teardown do
data/test/storage_test.rb CHANGED
@@ -3,6 +3,7 @@ require 'test/helper'
3
3
  class StorageTest < Test::Unit::TestCase
4
4
  context "Parsing S3 credentials" do
5
5
  setup do
6
+ AWS::S3::Base.stubs(:establish_connection!)
6
7
  rebuild_model :storage => :s3,
7
8
  :bucket => "testing",
8
9
  :s3_credentials => {:not => :important}
@@ -39,6 +40,7 @@ class StorageTest < Test::Unit::TestCase
39
40
 
40
41
  context "" do
41
42
  setup do
43
+ AWS::S3::Base.stubs(:establish_connection!)
42
44
  rebuild_model :storage => :s3,
43
45
  :s3_credentials => {},
44
46
  :bucket => "bucket",
@@ -54,6 +56,7 @@ class StorageTest < Test::Unit::TestCase
54
56
  end
55
57
  context "" do
56
58
  setup do
59
+ AWS::S3::Base.stubs(:establish_connection!)
57
60
  rebuild_model :storage => :s3,
58
61
  :s3_credentials => {},
59
62
  :bucket => "bucket",
@@ -69,6 +72,7 @@ class StorageTest < Test::Unit::TestCase
69
72
  end
70
73
  context "" do
71
74
  setup do
75
+ AWS::S3::Base.stubs(:establish_connection!)
72
76
  rebuild_model :storage => :s3,
73
77
  :s3_credentials => {
74
78
  :production => { :bucket => "prod_bucket" },
@@ -88,6 +92,7 @@ class StorageTest < Test::Unit::TestCase
88
92
 
89
93
  context "Parsing S3 credentials with a bucket in them" do
90
94
  setup do
95
+ AWS::S3::Base.stubs(:establish_connection!)
91
96
  rebuild_model :storage => :s3,
92
97
  :s3_credentials => {
93
98
  :production => { :bucket => "prod_bucket" },
@@ -146,14 +151,7 @@ class StorageTest < Test::Unit::TestCase
146
151
 
147
152
  context "and saved" do
148
153
  setup do
149
- @s3_mock = stub
150
- @bucket_mock = stub
151
- RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
152
- @s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
153
- @key_mock = stub
154
- @bucket_mock.expects(:key).returns(@key_mock)
155
- @key_mock.expects(:data=)
156
- @key_mock.expects(:put).with(nil, 'public-read', 'Content-type' => 'image/png')
154
+ AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path, anything, 'testing', :content_type => 'image/png', :access => :public_read)
157
155
  @dummy.save
158
156
  end
159
157
 
@@ -164,13 +162,8 @@ class StorageTest < Test::Unit::TestCase
164
162
 
165
163
  context "and remove" do
166
164
  setup do
167
- @s3_mock = stub
168
- @bucket_mock = stub
169
- RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
170
- @s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
171
- @key_mock = stub
172
- @bucket_mock.expects(:key).at_least(2).returns(@key_mock)
173
- @key_mock.expects(:delete)
165
+ AWS::S3::S3Object.stubs(:exists?).returns(true)
166
+ AWS::S3::S3Object.stubs(:delete)
174
167
  @dummy.destroy_attached_files
175
168
  end
176
169
 
@@ -183,6 +176,7 @@ class StorageTest < Test::Unit::TestCase
183
176
 
184
177
  context "An attachment with S3 storage and bucket defined as a Proc" do
185
178
  setup do
179
+ AWS::S3::Base.stubs(:establish_connection!)
186
180
  rebuild_model :storage => :s3,
187
181
  :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
188
182
  :s3_credentials => {:not => :important}
@@ -196,6 +190,7 @@ class StorageTest < Test::Unit::TestCase
196
190
 
197
191
  context "An attachment with S3 storage and specific s3 headers set" do
198
192
  setup do
193
+ AWS::S3::Base.stubs(:establish_connection!)
199
194
  rebuild_model :storage => :s3,
200
195
  :bucket => "testing",
201
196
  :path => ":attachment/:style/:basename.:extension",
@@ -217,17 +212,13 @@ class StorageTest < Test::Unit::TestCase
217
212
 
218
213
  context "and saved" do
219
214
  setup do
220
- @s3_mock = stub
221
- @bucket_mock = stub
222
- RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
223
- @s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
224
- @key_mock = stub
225
- @bucket_mock.expects(:key).returns(@key_mock)
226
- @key_mock.expects(:data=)
227
- @key_mock.expects(:put).with(nil,
228
- 'public-read',
229
- 'Content-type' => 'image/png',
230
- 'Cache-Control' => 'max-age=31557600')
215
+ AWS::S3::Base.stubs(:establish_connection!)
216
+ AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path,
217
+ anything,
218
+ 'testing',
219
+ :content_type => 'image/png',
220
+ :access => :public_read,
221
+ 'Cache-Control' => 'max-age=31557600')
231
222
  @dummy.save
232
223
  end
233
224
 
@@ -263,8 +254,8 @@ class StorageTest < Test::Unit::TestCase
263
254
 
264
255
  teardown { @file.close }
265
256
 
266
- should "still return a Tempfile when sent #to_io" do
267
- assert_equal Tempfile, @dummy.avatar.to_io.class
257
+ should "still return a Tempfile when sent #to_file" do
258
+ assert_equal Tempfile, @dummy.avatar.to_file.class
268
259
  end
269
260
 
270
261
  context "and saved" do
@@ -103,6 +103,44 @@ class ThumbnailTest < Test::Unit::TestCase
103
103
  end
104
104
  end
105
105
 
106
+ context "being thumbnailed with source file options set" do
107
+ setup do
108
+ @thumb = Paperclip::Thumbnail.new(@file,
109
+ :geometry => "100x50#",
110
+ :source_file_options => "-strip")
111
+ end
112
+
113
+ should "have source_file_options value set" do
114
+ assert_equal "-strip", @thumb.source_file_options
115
+ end
116
+
117
+ should "send the right command to convert when sent #make" do
118
+ Paperclip.expects(:"`").with do |arg|
119
+ arg.match %r{convert\s+-strip\s+"#{File.expand_path(@thumb.file.path)}\[0\]"\s+-resize\s+"x50"\s+-crop\s+"100x50\+114\+0"\s+\+repage\s+".*?"}
120
+ end
121
+ @thumb.make
122
+ end
123
+
124
+ should "create the thumbnail when sent #make" do
125
+ dst = @thumb.make
126
+ assert_match /100x50/, `identify "#{dst.path}"`
127
+ end
128
+
129
+ context "redefined to have bad source_file_options setting" do
130
+ setup do
131
+ @thumb = Paperclip::Thumbnail.new(@file,
132
+ :geometry => "100x50#",
133
+ :source_file_options => "-this-aint-no-option")
134
+ end
135
+
136
+ should "error when trying to create the thumbnail" do
137
+ assert_raises(Paperclip::PaperclipError) do
138
+ @thumb.make
139
+ end
140
+ end
141
+ end
142
+ end
143
+
106
144
  context "being thumbnailed with convert options set" do
107
145
  setup do
108
146
  @thumb = Paperclip::Thumbnail.new(@file,
@@ -140,6 +178,18 @@ class ThumbnailTest < Test::Unit::TestCase
140
178
  end
141
179
  end
142
180
  end
181
+
182
+ context "being thumbnailed with a blank geometry string" do
183
+ setup do
184
+ @thumb = Paperclip::Thumbnail.new(@file,
185
+ :geometry => "",
186
+ :convert_options => "-gravity center -crop \"300x300+0-0\"")
187
+ end
188
+
189
+ should "not get resized by default" do
190
+ assert_no_match(/-resize/, @thumb.transformation_command)
191
+ end
192
+ end
143
193
  end
144
194
 
145
195
  context "A multipage PDF" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joshpuetz-paperclip
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0.1
4
+ version: 2.3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Yurek
@@ -95,7 +95,6 @@ files:
95
95
  - shoulda_macros/paperclip.rb
96
96
  has_rdoc: true
97
97
  homepage: http://www.thoughtbot.com/projects/paperclip
98
- licenses:
99
98
  post_install_message:
100
99
  rdoc_options:
101
100
  - --line-numbers
@@ -117,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
116
  requirements:
118
117
  - ImageMagick
119
118
  rubyforge_project: paperclip
120
- rubygems_version: 1.3.5
119
+ rubygems_version: 1.2.0
121
120
  signing_key:
122
121
  specification_version: 2
123
122
  summary: File attachments as attributes for ActiveRecord