paperclip 3.0.4 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- data/Appraisals +3 -3
- data/NEWS +43 -0
- data/README.md +81 -5
- data/features/basic_integration.feature +20 -2
- data/features/migration.feature +94 -0
- data/features/step_definitions/attachment_steps.rb +28 -0
- data/features/step_definitions/rails_steps.rb +19 -1
- data/features/step_definitions/web_steps.rb +3 -3
- data/gemfiles/3.0.gemfile +1 -1
- data/gemfiles/3.1.gemfile +1 -1
- data/gemfiles/3.2.gemfile +1 -1
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +4 -8
- data/lib/paperclip.rb +2 -0
- data/lib/paperclip/attachment.rb +4 -0
- data/lib/paperclip/geometry.rb +33 -0
- data/lib/paperclip/glue.rb +2 -1
- data/lib/paperclip/io_adapters/abstract_adapter.rb +45 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +13 -48
- data/lib/paperclip/io_adapters/file_adapter.rb +11 -61
- data/lib/paperclip/io_adapters/identity_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/nil_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/stringio_adapter.rb +11 -42
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +6 -45
- data/lib/paperclip/matchers.rb +2 -2
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +36 -17
- data/lib/paperclip/railtie.rb +5 -1
- data/lib/paperclip/schema.rb +59 -23
- data/lib/paperclip/storage/filesystem.rb +5 -0
- data/lib/paperclip/storage/fog.rb +36 -14
- data/lib/paperclip/storage/s3.rb +14 -16
- data/lib/paperclip/style.rb +2 -2
- data/lib/paperclip/tempfile_factory.rb +21 -0
- data/lib/paperclip/thumbnail.rb +10 -1
- data/lib/paperclip/version.rb +1 -1
- data/paperclip.gemspec +1 -1
- data/test/attachment_test.rb +56 -24
- data/test/fixtures/animated +0 -0
- data/test/fixtures/animated.unknown +0 -0
- data/test/generator_test.rb +26 -24
- data/test/geometry_test.rb +19 -0
- data/test/helper.rb +8 -0
- data/test/integration_test.rb +23 -23
- data/test/io_adapters/abstract_adapter_test.rb +44 -0
- data/test/io_adapters/attachment_adapter_test.rb +96 -34
- data/test/io_adapters/file_adapter_test.rb +13 -1
- data/test/io_adapters/stringio_adapter_test.rb +9 -10
- data/test/io_adapters/uploaded_file_adapter_test.rb +2 -1
- data/test/schema_test.rb +179 -77
- data/test/storage/filesystem_test.rb +18 -3
- data/test/storage/fog_test.rb +64 -1
- data/test/storage/s3_test.rb +38 -2
- data/test/tempfile_factory_test.rb +13 -0
- data/test/thumbnail_test.rb +45 -0
- metadata +16 -9
- data/features/support/fixtures/.boot_config.rb.swo +0 -0
- data/images.rake +0 -21
data/lib/paperclip/version.rb
CHANGED
data/paperclip.gemspec
CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do |s|
|
|
37
37
|
s.add_development_dependency('aws-sdk')
|
38
38
|
s.add_development_dependency('bourne')
|
39
39
|
s.add_development_dependency('sqlite3', '~> 1.3.4')
|
40
|
-
s.add_development_dependency('cucumber', '~> 1.1
|
40
|
+
s.add_development_dependency('cucumber', '~> 1.2.1')
|
41
41
|
s.add_development_dependency('aruba')
|
42
42
|
s.add_development_dependency('nokogiri')
|
43
43
|
s.add_development_dependency('capybara')
|
data/test/attachment_test.rb
CHANGED
@@ -28,15 +28,15 @@ class AttachmentTest < Test::Unit::TestCase
|
|
28
28
|
dummy.avatar = file
|
29
29
|
dummy.save
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
assert_file_exists(dummy.avatar.path(:small))
|
32
|
+
assert_file_exists(dummy.avatar.path(:large))
|
33
|
+
assert_file_exists(dummy.avatar.path(:original))
|
34
34
|
|
35
35
|
dummy.avatar.reprocess!(:small)
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
assert_file_exists(dummy.avatar.path(:small))
|
38
|
+
assert_file_exists(dummy.avatar.path(:large))
|
39
|
+
assert_file_exists(dummy.avatar.path(:original))
|
40
40
|
end
|
41
41
|
|
42
42
|
should "handle a boolean second argument to #url" do
|
@@ -742,21 +742,53 @@ class AttachmentTest < Test::Unit::TestCase
|
|
742
742
|
context "Attachment with reserved filename" do
|
743
743
|
setup do
|
744
744
|
rebuild_model
|
745
|
-
@file =
|
745
|
+
@file = Tempfile.new(["filename","png"])
|
746
|
+
end
|
747
|
+
|
748
|
+
teardown do
|
749
|
+
@file.unlink
|
746
750
|
end
|
747
751
|
|
748
752
|
context "with default configuration" do
|
749
753
|
"&$+,/:;=?@<>[]{}|\^~%# ".split(//).each do |character|
|
750
754
|
context "with character #{character}" do
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
+
|
756
|
+
context "at beginning of filename" do
|
757
|
+
setup do
|
758
|
+
@file.stubs(:original_filename).returns("#{character}filename.png")
|
759
|
+
@dummy = Dummy.new
|
760
|
+
@dummy.avatar = @file
|
761
|
+
end
|
762
|
+
|
763
|
+
should "convert special character into underscore" do
|
764
|
+
assert_equal "_filename.png", @dummy.avatar.original_filename
|
765
|
+
end
|
766
|
+
end
|
767
|
+
|
768
|
+
context "at end of filename" do
|
769
|
+
setup do
|
770
|
+
@file.stubs(:original_filename).returns("filename.png#{character}")
|
771
|
+
@dummy = Dummy.new
|
772
|
+
@dummy.avatar = @file
|
773
|
+
end
|
774
|
+
|
775
|
+
should "convert special character into underscore" do
|
776
|
+
assert_equal "filename.png_", @dummy.avatar.original_filename
|
777
|
+
end
|
755
778
|
end
|
756
779
|
|
757
|
-
|
758
|
-
|
780
|
+
context "in the middle of filename" do
|
781
|
+
setup do
|
782
|
+
@file.stubs(:original_filename).returns("file#{character}name.png")
|
783
|
+
@dummy = Dummy.new
|
784
|
+
@dummy.avatar = @file
|
785
|
+
end
|
786
|
+
|
787
|
+
should "convert special character into underscore" do
|
788
|
+
assert_equal "file_name.png", @dummy.avatar.original_filename
|
789
|
+
end
|
759
790
|
end
|
791
|
+
|
760
792
|
end
|
761
793
|
end
|
762
794
|
end
|
@@ -925,7 +957,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
925
957
|
|
926
958
|
should "commit the files to disk" do
|
927
959
|
[:large, :medium, :small].each do |style|
|
928
|
-
|
960
|
+
assert_file_exists(@attachment.path(style))
|
929
961
|
end
|
930
962
|
end
|
931
963
|
|
@@ -957,7 +989,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
957
989
|
@attachment.expects(:instance_write).with(:updated_at, nil)
|
958
990
|
@attachment.assign nil
|
959
991
|
@attachment.save
|
960
|
-
@existing_names.each{|f|
|
992
|
+
@existing_names.each{|f| assert_file_not_exists(f) }
|
961
993
|
end
|
962
994
|
|
963
995
|
should "delete the files when you call #clear and #save" do
|
@@ -968,7 +1000,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
968
1000
|
@attachment.expects(:instance_write).with(:updated_at, nil)
|
969
1001
|
@attachment.clear
|
970
1002
|
@attachment.save
|
971
|
-
@existing_names.each{|f|
|
1003
|
+
@existing_names.each{|f| assert_file_not_exists(f) }
|
972
1004
|
end
|
973
1005
|
|
974
1006
|
should "delete the files when you call #delete" do
|
@@ -978,7 +1010,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
978
1010
|
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
979
1011
|
@attachment.expects(:instance_write).with(:updated_at, nil)
|
980
1012
|
@attachment.destroy
|
981
|
-
@existing_names.each{|f|
|
1013
|
+
@existing_names.each{|f| assert_file_not_exists(f) }
|
982
1014
|
end
|
983
1015
|
|
984
1016
|
context "when keeping old files" do
|
@@ -994,7 +1026,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
994
1026
|
@attachment.expects(:instance_write).with(:updated_at, nil)
|
995
1027
|
@attachment.assign nil
|
996
1028
|
@attachment.save
|
997
|
-
@existing_names.each{|f|
|
1029
|
+
@existing_names.each{|f| assert_file_exists(f) }
|
998
1030
|
end
|
999
1031
|
|
1000
1032
|
should "keep the files when you call #clear and #save" do
|
@@ -1005,7 +1037,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
1005
1037
|
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1006
1038
|
@attachment.clear
|
1007
1039
|
@attachment.save
|
1008
|
-
@existing_names.each{|f|
|
1040
|
+
@existing_names.each{|f| assert_file_exists(f) }
|
1009
1041
|
end
|
1010
1042
|
|
1011
1043
|
should "keep the files when you call #delete" do
|
@@ -1015,7 +1047,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
1015
1047
|
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1016
1048
|
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1017
1049
|
@attachment.destroy
|
1018
|
-
@existing_names.each{|f|
|
1050
|
+
@existing_names.each{|f| assert_file_exists(f) }
|
1019
1051
|
end
|
1020
1052
|
end
|
1021
1053
|
end
|
@@ -1174,12 +1206,12 @@ class AttachmentTest < Test::Unit::TestCase
|
|
1174
1206
|
|
1175
1207
|
should "not delete the files from storage when attachment is destroyed" do
|
1176
1208
|
@attachment.destroy
|
1177
|
-
|
1209
|
+
assert_file_exists(@path)
|
1178
1210
|
end
|
1179
1211
|
|
1180
1212
|
should "not delete the file when model is destroyed" do
|
1181
1213
|
@dummy.destroy
|
1182
|
-
|
1214
|
+
assert_file_exists(@path)
|
1183
1215
|
end
|
1184
1216
|
end
|
1185
1217
|
|
@@ -1203,12 +1235,12 @@ class AttachmentTest < Test::Unit::TestCase
|
|
1203
1235
|
@dummy.destroy
|
1204
1236
|
end
|
1205
1237
|
|
1206
|
-
|
1238
|
+
assert_file_exists(@path)
|
1207
1239
|
end
|
1208
1240
|
|
1209
1241
|
should "be deleted when the model is destroyed" do
|
1210
1242
|
@dummy.destroy
|
1211
|
-
|
1243
|
+
assert_file_not_exists(@path)
|
1212
1244
|
end
|
1213
1245
|
end
|
1214
1246
|
|
Binary file
|
Binary file
|
data/test/generator_test.rb
CHANGED
@@ -18,17 +18,21 @@ class GeneratorTest < Rails::Generators::TestCase
|
|
18
18
|
assert_match /class AddAttachmentAvatarToUsers/, migration
|
19
19
|
|
20
20
|
assert_class_method :up, migration do |up|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
expected = <<-migration
|
22
|
+
change_table :users do |t|
|
23
|
+
t.has_attached_file :avatar
|
24
|
+
end
|
25
|
+
migration
|
26
|
+
|
27
|
+
assert_equal expected.squish, up.squish
|
25
28
|
end
|
26
29
|
|
27
30
|
assert_class_method :down, migration do |down|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
expected = <<-migration
|
32
|
+
drop_attached_file :users, :avatar
|
33
|
+
migration
|
34
|
+
|
35
|
+
assert_equal expected.squish, down.squish
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -44,25 +48,23 @@ class GeneratorTest < Rails::Generators::TestCase
|
|
44
48
|
assert_match /class AddAttachmentAvatarPhotoToUsers/, migration
|
45
49
|
|
46
50
|
assert_class_method :up, migration do |up|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
expected = <<-migration
|
52
|
+
change_table :users do |t|
|
53
|
+
t.has_attached_file :avatar
|
54
|
+
t.has_attached_file :photo
|
55
|
+
end
|
56
|
+
migration
|
57
|
+
|
58
|
+
assert_equal expected.squish, up.squish
|
55
59
|
end
|
56
60
|
|
57
61
|
assert_class_method :down, migration do |down|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
assert_match /remove_column :users, :photo_file_size/, down
|
65
|
-
assert_match /remove_column :users, :photo_updated_at/, down
|
62
|
+
expected = <<-migration
|
63
|
+
drop_attached_file :users, :avatar
|
64
|
+
drop_attached_file :users, :photo
|
65
|
+
migration
|
66
|
+
|
67
|
+
assert_equal expected.squish, down.squish
|
66
68
|
end
|
67
69
|
end
|
68
70
|
end
|
data/test/geometry_test.rb
CHANGED
@@ -202,5 +202,24 @@ class GeometryTest < Test::Unit::TestCase
|
|
202
202
|
end
|
203
203
|
end
|
204
204
|
end
|
205
|
+
|
206
|
+
[['256x256', '150x150!' => [150, 150], '150x150#' => [150, 150], '150x150>' => [150, 150], '150x150<' => [256, 256], '150x150' => [150, 150]],
|
207
|
+
['256x256', '512x512!' => [512, 512], '512x512#' => [512, 512], '512x512>' => [256, 256], '512x512<' => [512, 512], '512x512' => [512, 512]],
|
208
|
+
['600x400', '512x512!' => [512, 512], '512x512#' => [512, 512], '512x512>' => [512, 341], '512x512<' => [600, 400], '512x512' => [512, 341]]].each do |original_size, options|
|
209
|
+
options.each_pair do |size, dimensions|
|
210
|
+
context "#{original_size} resize_to #{size}" do
|
211
|
+
setup do
|
212
|
+
@source = Paperclip::Geometry.parse original_size
|
213
|
+
@new_geometry = @source.resize_to size
|
214
|
+
end
|
215
|
+
should "have #{dimensions.first} width" do
|
216
|
+
assert_equal dimensions.first, @new_geometry.width
|
217
|
+
end
|
218
|
+
should "have #{dimensions.last} height" do
|
219
|
+
assert_equal dimensions.last, @new_geometry.height
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
205
224
|
end
|
206
225
|
end
|
data/test/helper.rb
CHANGED
@@ -177,3 +177,11 @@ def assert_not_found_response(url)
|
|
177
177
|
"Expected HTTP response code 404, got #{response.code}"
|
178
178
|
end
|
179
179
|
end
|
180
|
+
|
181
|
+
def assert_file_exists(path)
|
182
|
+
assert File.exists?(path), %(Expect "#{path}" to be exists.)
|
183
|
+
end
|
184
|
+
|
185
|
+
def assert_file_not_exists(path)
|
186
|
+
assert !File.exists?(path), %(Expect "#{path}" to not exists.)
|
187
|
+
end
|
data/test/integration_test.rb
CHANGED
@@ -96,14 +96,14 @@ class IntegrationTest < Test::Unit::TestCase
|
|
96
96
|
@dummy.avatar.post_processing = false
|
97
97
|
@dummy.avatar = @file
|
98
98
|
assert @dummy.save
|
99
|
-
|
99
|
+
assert_file_not_exists @thumb_path
|
100
100
|
end
|
101
101
|
|
102
102
|
should "create the thumbnails upon saving when post_processing is enabled" do
|
103
103
|
@dummy.avatar.post_processing = true
|
104
104
|
@dummy.avatar = @file
|
105
105
|
assert @dummy.save
|
106
|
-
|
106
|
+
assert_file_exists @thumb_path
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
@@ -126,25 +126,25 @@ class IntegrationTest < Test::Unit::TestCase
|
|
126
126
|
teardown { @file.close }
|
127
127
|
|
128
128
|
should "allow us to create all thumbnails in one go" do
|
129
|
-
|
130
|
-
|
129
|
+
assert_file_not_exists(@thumb_small_path)
|
130
|
+
assert_file_not_exists(@thumb_large_path)
|
131
131
|
|
132
132
|
@dummy.avatar.reprocess!
|
133
133
|
|
134
|
-
|
135
|
-
|
134
|
+
assert_file_exists(@thumb_small_path)
|
135
|
+
assert_file_exists(@thumb_large_path)
|
136
136
|
end
|
137
137
|
|
138
138
|
should "allow us to selectively create each thumbnail" do
|
139
|
-
|
140
|
-
|
139
|
+
assert_file_not_exists(@thumb_small_path)
|
140
|
+
assert_file_not_exists(@thumb_large_path)
|
141
141
|
|
142
142
|
@dummy.avatar.reprocess! :thumb_small
|
143
|
-
|
144
|
-
|
143
|
+
assert_file_exists(@thumb_small_path)
|
144
|
+
assert_file_not_exists(@thumb_large_path)
|
145
145
|
|
146
146
|
@dummy.avatar.reprocess! :thumb_large
|
147
|
-
|
147
|
+
assert_file_exists(@thumb_large_path)
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
@@ -182,7 +182,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
182
182
|
end
|
183
183
|
|
184
184
|
should "have a large file in the right place" do
|
185
|
-
|
185
|
+
assert_file_exists(@dummy.avatar.path(:large))
|
186
186
|
end
|
187
187
|
|
188
188
|
context "and deleted" do
|
@@ -192,12 +192,12 @@ class IntegrationTest < Test::Unit::TestCase
|
|
192
192
|
end
|
193
193
|
|
194
194
|
should "not have a large file in the right place anymore" do
|
195
|
-
|
195
|
+
assert_file_not_exists(@saved_path)
|
196
196
|
end
|
197
197
|
|
198
198
|
should "not have its next two parent directories" do
|
199
|
-
|
200
|
-
|
199
|
+
assert_file_not_exists(File.dirname(@saved_path))
|
200
|
+
assert_file_not_exists(File.dirname(File.dirname(@saved_path)))
|
201
201
|
end
|
202
202
|
|
203
203
|
before_should "not die if an unexpected SystemCallError happens" do
|
@@ -334,7 +334,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
334
334
|
assert @dummy.save
|
335
335
|
|
336
336
|
saved_paths.each do |p|
|
337
|
-
|
337
|
+
assert_file_exists(p)
|
338
338
|
end
|
339
339
|
|
340
340
|
@dummy.avatar.clear
|
@@ -343,7 +343,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
343
343
|
assert @dummy.save
|
344
344
|
|
345
345
|
saved_paths.each do |p|
|
346
|
-
|
346
|
+
assert_file_not_exists(p)
|
347
347
|
end
|
348
348
|
|
349
349
|
@d2 = Dummy.find(@dummy.id)
|
@@ -364,7 +364,7 @@ class IntegrationTest < Test::Unit::TestCase
|
|
364
364
|
assert @d2.save
|
365
365
|
|
366
366
|
saved_paths.each do |p|
|
367
|
-
|
367
|
+
assert_file_not_exists(p)
|
368
368
|
end
|
369
369
|
end
|
370
370
|
|
@@ -457,8 +457,8 @@ class IntegrationTest < Test::Unit::TestCase
|
|
457
457
|
end
|
458
458
|
|
459
459
|
should "be accessible" do
|
460
|
-
|
461
|
-
|
460
|
+
assert_file_exists(@dummy.avatar.path(:original))
|
461
|
+
assert_file_exists(@dummy.avatar.path(:thumb))
|
462
462
|
end
|
463
463
|
|
464
464
|
context "when new style is added" do
|
@@ -469,9 +469,9 @@ class IntegrationTest < Test::Unit::TestCase
|
|
469
469
|
end
|
470
470
|
|
471
471
|
should "make all the styles accessible" do
|
472
|
-
|
473
|
-
|
474
|
-
|
472
|
+
assert_file_exists(@dummy.avatar.path(:original))
|
473
|
+
assert_file_exists(@dummy.avatar.path(:thumb))
|
474
|
+
assert_file_exists(@dummy.avatar.path(:mini))
|
475
475
|
end
|
476
476
|
end
|
477
477
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require './test/helper'
|
2
|
+
|
3
|
+
class AbstractAdapterTest < Test::Unit::TestCase
|
4
|
+
class TestAdapter < Paperclip::AbstractAdapter
|
5
|
+
attr_accessor :original_file_name, :tempfile
|
6
|
+
|
7
|
+
def content_type
|
8
|
+
type_from_file_command
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "content type from file command" do
|
13
|
+
setup do
|
14
|
+
@adapter = TestAdapter.new
|
15
|
+
@adapter.stubs(:path)
|
16
|
+
Paperclip.stubs(:run).returns("image/png\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
should "return the content type without newline" do
|
20
|
+
assert_equal "image/png", @adapter.content_type
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "nil?" do
|
25
|
+
should "return false" do
|
26
|
+
assert !TestAdapter.new.nil?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "delegation" do
|
31
|
+
setup do
|
32
|
+
@adapter = TestAdapter.new
|
33
|
+
@adapter.tempfile = stub("Tempfile")
|
34
|
+
end
|
35
|
+
|
36
|
+
[:close, :closed?, :eof?, :path, :rewind, :unlink].each do |method|
|
37
|
+
should "delegate #{method} to @tempfile" do
|
38
|
+
@adapter.tempfile.stubs(method)
|
39
|
+
@adapter.public_send(method)
|
40
|
+
assert_received @adapter.tempfile, method
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|