jmcnevin-paperclip 2.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/LICENSE +26 -0
  2. data/README.md +414 -0
  3. data/Rakefile +86 -0
  4. data/generators/paperclip/USAGE +5 -0
  5. data/generators/paperclip/paperclip_generator.rb +27 -0
  6. data/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  7. data/init.rb +4 -0
  8. data/lib/generators/paperclip/USAGE +8 -0
  9. data/lib/generators/paperclip/paperclip_generator.rb +33 -0
  10. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +19 -0
  11. data/lib/paperclip.rb +480 -0
  12. data/lib/paperclip/attachment.rb +520 -0
  13. data/lib/paperclip/callback_compatibility.rb +61 -0
  14. data/lib/paperclip/geometry.rb +155 -0
  15. data/lib/paperclip/interpolations.rb +171 -0
  16. data/lib/paperclip/iostream.rb +45 -0
  17. data/lib/paperclip/matchers.rb +33 -0
  18. data/lib/paperclip/matchers/have_attached_file_matcher.rb +57 -0
  19. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +81 -0
  20. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +54 -0
  21. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +95 -0
  22. data/lib/paperclip/missing_attachment_styles.rb +87 -0
  23. data/lib/paperclip/options.rb +78 -0
  24. data/lib/paperclip/processor.rb +58 -0
  25. data/lib/paperclip/railtie.rb +26 -0
  26. data/lib/paperclip/storage.rb +3 -0
  27. data/lib/paperclip/storage/filesystem.rb +81 -0
  28. data/lib/paperclip/storage/fog.rb +163 -0
  29. data/lib/paperclip/storage/s3.rb +270 -0
  30. data/lib/paperclip/style.rb +95 -0
  31. data/lib/paperclip/thumbnail.rb +105 -0
  32. data/lib/paperclip/upfile.rb +62 -0
  33. data/lib/paperclip/version.rb +3 -0
  34. data/lib/tasks/paperclip.rake +101 -0
  35. data/rails/init.rb +2 -0
  36. data/shoulda_macros/paperclip.rb +124 -0
  37. data/test/attachment_test.rb +1161 -0
  38. data/test/database.yml +4 -0
  39. data/test/fixtures/12k.png +0 -0
  40. data/test/fixtures/50x50.png +0 -0
  41. data/test/fixtures/5k.png +0 -0
  42. data/test/fixtures/animated.gif +0 -0
  43. data/test/fixtures/bad.png +1 -0
  44. data/test/fixtures/double spaces in name.png +0 -0
  45. data/test/fixtures/fog.yml +8 -0
  46. data/test/fixtures/s3.yml +8 -0
  47. data/test/fixtures/spaced file.png +0 -0
  48. data/test/fixtures/text.txt +1 -0
  49. data/test/fixtures/twopage.pdf +0 -0
  50. data/test/fixtures/uppercase.PNG +0 -0
  51. data/test/fog_test.rb +192 -0
  52. data/test/geometry_test.rb +206 -0
  53. data/test/helper.rb +158 -0
  54. data/test/integration_test.rb +781 -0
  55. data/test/interpolations_test.rb +202 -0
  56. data/test/iostream_test.rb +71 -0
  57. data/test/matchers/have_attached_file_matcher_test.rb +24 -0
  58. data/test/matchers/validate_attachment_content_type_matcher_test.rb +87 -0
  59. data/test/matchers/validate_attachment_presence_matcher_test.rb +26 -0
  60. data/test/matchers/validate_attachment_size_matcher_test.rb +51 -0
  61. data/test/options_test.rb +75 -0
  62. data/test/paperclip_missing_attachment_styles_test.rb +80 -0
  63. data/test/paperclip_test.rb +340 -0
  64. data/test/processor_test.rb +10 -0
  65. data/test/storage/filesystem_test.rb +56 -0
  66. data/test/storage/s3_live_test.rb +88 -0
  67. data/test/storage/s3_test.rb +689 -0
  68. data/test/style_test.rb +180 -0
  69. data/test/thumbnail_test.rb +383 -0
  70. data/test/upfile_test.rb +53 -0
  71. metadata +294 -0
@@ -0,0 +1,180 @@
1
+ # encoding: utf-8
2
+ require './test/helper'
3
+
4
+ class StyleTest < Test::Unit::TestCase
5
+
6
+ context "A style rule" do
7
+ setup do
8
+ @attachment = attachment :path => ":basename.:extension",
9
+ :styles => { :foo => {:geometry => "100x100#", :format => :png} },
10
+ :whiny => true
11
+ @style = @attachment.options.styles[:foo]
12
+ end
13
+
14
+ should "be held as a Style object" do
15
+ assert_kind_of Paperclip::Style, @style
16
+ end
17
+
18
+ should "get processors from the attachment definition" do
19
+ assert_equal [:thumbnail], @style.processors
20
+ end
21
+
22
+ should "have the right geometry" do
23
+ assert_equal "100x100#", @style.geometry
24
+ end
25
+
26
+ should "be whiny if the attachment is" do
27
+ assert @style.whiny?
28
+ end
29
+
30
+ should "respond to hash notation" do
31
+ assert_equal [:thumbnail], @style[:processors]
32
+ assert_equal "100x100#", @style[:geometry]
33
+ end
34
+ end
35
+
36
+ context "A style rule with properties supplied as procs" do
37
+ setup do
38
+ @attachment = attachment :path => ":basename.:extension",
39
+ :whiny_thumbnails => true,
40
+ :processors => lambda {|a| [:test]},
41
+ :styles => {
42
+ :foo => lambda{|a| "300x300#"},
43
+ :bar => {
44
+ :geometry => lambda{|a| "300x300#"}
45
+ }
46
+ }
47
+ end
48
+
49
+ should "call procs when they are needed" do
50
+ assert_equal "300x300#", @attachment.options.styles[:foo].geometry
51
+ assert_equal "300x300#", @attachment.options.styles[:bar].geometry
52
+ assert_equal [:test], @attachment.options.styles[:foo].processors
53
+ assert_equal [:test], @attachment.options.styles[:bar].processors
54
+ end
55
+ end
56
+
57
+ context "An attachment with style rules in various forms" do
58
+ setup do
59
+ styles = ActiveSupport::OrderedHash.new
60
+ styles[:aslist] = ["100x100", :png]
61
+ styles[:ashash] = {:geometry => "100x100", :format => :png}
62
+ styles[:asstring] = "100x100"
63
+ @attachment = attachment :path => ":basename.:extension",
64
+ :styles => styles
65
+ end
66
+ should "have the right number of styles" do
67
+ assert_kind_of Hash, @attachment.options.styles
68
+ assert_equal 3, @attachment.options.styles.size
69
+ end
70
+
71
+ should "have styles as Style objects" do
72
+ [:aslist, :ashash, :aslist].each do |s|
73
+ assert_kind_of Paperclip::Style, @attachment.options.styles[s]
74
+ end
75
+ end
76
+
77
+ should "have the right geometries" do
78
+ [:aslist, :ashash, :aslist].each do |s|
79
+ assert_equal @attachment.options.styles[s].geometry, "100x100"
80
+ end
81
+ end
82
+
83
+ should "have the right formats" do
84
+ assert_equal @attachment.options.styles[:aslist].format, :png
85
+ assert_equal @attachment.options.styles[:ashash].format, :png
86
+ assert_nil @attachment.options.styles[:asstring].format
87
+ end
88
+
89
+ should "retain order" do
90
+ assert_equal [:aslist, :ashash, :asstring], @attachment.options.styles.keys
91
+ end
92
+ end
93
+
94
+ context "An attachment with :convert_options" do
95
+ setup do
96
+ @attachment = attachment :path => ":basename.:extension",
97
+ :styles => {:thumb => "100x100", :large => "400x400"},
98
+ :convert_options => {:all => "-do_stuff", :thumb => "-thumbnailize"}
99
+ @style = @attachment.options.styles[:thumb]
100
+ @file = StringIO.new("...")
101
+ @file.stubs(:original_filename).returns("file.jpg")
102
+ end
103
+
104
+ before_should "not have called extra_options_for(:thumb/:large) on initialization" do
105
+ @attachment.expects(:extra_options_for).never
106
+ end
107
+
108
+ should "call extra_options_for(:thumb/:large) when convert options are requested" do
109
+ @attachment.expects(:extra_options_for).with(:thumb)
110
+ @attachment.options.styles[:thumb].convert_options
111
+ end
112
+ end
113
+
114
+ context "An attachment with :source_file_options" do
115
+ setup do
116
+ @attachment = attachment :path => ":basename.:extension",
117
+ :styles => {:thumb => "100x100", :large => "400x400"},
118
+ :source_file_options => {:all => "-density 400", :thumb => "-depth 8"}
119
+ @style = @attachment.options.styles[:thumb]
120
+ @file = StringIO.new("...")
121
+ @file.stubs(:original_filename).returns("file.jpg")
122
+ end
123
+
124
+ before_should "not have called extra_source_file_options_for(:thumb/:large) on initialization" do
125
+ @attachment.expects(:extra_source_file_options_for).never
126
+ end
127
+
128
+ should "call extra_options_for(:thumb/:large) when convert options are requested" do
129
+ @attachment.expects(:extra_source_file_options_for).with(:thumb)
130
+ @attachment.options.styles[:thumb].source_file_options
131
+ end
132
+ end
133
+
134
+ context "A style rule with its own :processors" do
135
+ setup do
136
+ @attachment = attachment :path => ":basename.:extension",
137
+ :styles => {
138
+ :foo => {
139
+ :geometry => "100x100#",
140
+ :format => :png,
141
+ :processors => [:test]
142
+ }
143
+ },
144
+ :processors => [:thumbnail]
145
+ @style = @attachment.options.styles[:foo]
146
+ end
147
+
148
+ should "not get processors from the attachment" do
149
+ @attachment.expects(:processors).never
150
+ assert_not_equal [:thumbnail], @style.processors
151
+ end
152
+
153
+ should "report its own processors" do
154
+ assert_equal [:test], @style.processors
155
+ end
156
+
157
+ end
158
+
159
+ context "A style rule with :processors supplied as procs" do
160
+ setup do
161
+ @attachment = attachment :path => ":basename.:extension",
162
+ :styles => {
163
+ :foo => {
164
+ :geometry => "100x100#",
165
+ :format => :png,
166
+ :processors => lambda{|a| [:test]}
167
+ }
168
+ },
169
+ :processors => [:thumbnail]
170
+ end
171
+
172
+ should "defer processing of procs until they are needed" do
173
+ assert_kind_of Proc, @attachment.options.styles[:foo].instance_variable_get("@processors")
174
+ end
175
+
176
+ should "call procs when they are needed" do
177
+ assert_equal [:test], @attachment.options.styles[:foo].processors
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,383 @@
1
+ require './test/helper'
2
+
3
+ class ThumbnailTest < Test::Unit::TestCase
4
+
5
+ context "A Paperclip Tempfile" do
6
+ setup do
7
+ @tempfile = Paperclip::Tempfile.new(["file", ".jpg"])
8
+ end
9
+
10
+ should "have its path contain a real extension" do
11
+ assert_equal ".jpg", File.extname(@tempfile.path)
12
+ end
13
+
14
+ should "be a real Tempfile" do
15
+ assert @tempfile.is_a?(::Tempfile)
16
+ end
17
+ end
18
+
19
+ context "Another Paperclip Tempfile" do
20
+ setup do
21
+ @tempfile = Paperclip::Tempfile.new("file")
22
+ end
23
+
24
+ should "not have an extension if not given one" do
25
+ assert_equal "", File.extname(@tempfile.path)
26
+ end
27
+
28
+ should "still be a real Tempfile" do
29
+ assert @tempfile.is_a?(::Tempfile)
30
+ end
31
+ end
32
+
33
+ context "An image" do
34
+ setup do
35
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
36
+ end
37
+
38
+ teardown { @file.close }
39
+
40
+ [["600x600>", "434x66"],
41
+ ["400x400>", "400x61"],
42
+ ["32x32<", "434x66"]
43
+ ].each do |args|
44
+ context "being thumbnailed with a geometry of #{args[0]}" do
45
+ setup do
46
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => args[0])
47
+ end
48
+
49
+ should "start with dimensions of 434x66" do
50
+ cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
51
+ assert_equal "434x66", `#{cmd}`.chomp
52
+ end
53
+
54
+ should "report the correct target geometry" do
55
+ assert_equal args[0], @thumb.target_geometry.to_s
56
+ end
57
+
58
+ context "when made" do
59
+ setup do
60
+ @thumb_result = @thumb.make
61
+ end
62
+
63
+ should "be the size we expect it to be" do
64
+ cmd = %Q[identify -format "%wx%h" "#{@thumb_result.path}"]
65
+ assert_equal args[1], `#{cmd}`.chomp
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ context "being thumbnailed at 100x50 with cropping" do
72
+ setup do
73
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x50#")
74
+ end
75
+
76
+ should "let us know when a command isn't found versus a processing error" do
77
+ old_path = ENV['PATH']
78
+ begin
79
+ ENV['PATH'] = ''
80
+ assert_raises(Paperclip::CommandNotFoundError) do
81
+ @thumb.make
82
+ end
83
+ ensure
84
+ ENV['PATH'] = old_path
85
+ end
86
+ end
87
+
88
+ should "report its correct current and target geometries" do
89
+ assert_equal "100x50#", @thumb.target_geometry.to_s
90
+ assert_equal "434x66", @thumb.current_geometry.to_s
91
+ end
92
+
93
+ should "report its correct format" do
94
+ assert_nil @thumb.format
95
+ end
96
+
97
+ should "have whiny turned on by default" do
98
+ assert @thumb.whiny
99
+ end
100
+
101
+ should "have convert_options set to nil by default" do
102
+ assert_equal nil, @thumb.convert_options
103
+ end
104
+
105
+ should "have source_file_options set to nil by default" do
106
+ assert_equal nil, @thumb.source_file_options
107
+ end
108
+
109
+ should "send the right command to convert when sent #make" do
110
+ Paperclip.expects(:run).with do |*arg|
111
+ arg[0] == 'convert' &&
112
+ arg[1] == ':source -resize "x50" -crop "100x50+114+0" +repage :dest' &&
113
+ arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
114
+ end
115
+ @thumb.make
116
+ end
117
+
118
+ should "create the thumbnail when sent #make" do
119
+ dst = @thumb.make
120
+ assert_match /100x50/, `identify "#{dst.path}"`
121
+ end
122
+ end
123
+
124
+ context "being thumbnailed with source file options set" do
125
+ setup do
126
+ @thumb = Paperclip::Thumbnail.new(@file,
127
+ :geometry => "100x50#",
128
+ :source_file_options => "-strip")
129
+ end
130
+
131
+ should "have source_file_options value set" do
132
+ assert_equal ["-strip"], @thumb.source_file_options
133
+ end
134
+
135
+ should "send the right command to convert when sent #make" do
136
+ Paperclip.expects(:run).with do |*arg|
137
+ arg[0] == 'convert' &&
138
+ arg[1] == '-strip :source -resize "x50" -crop "100x50+114+0" +repage :dest' &&
139
+ arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
140
+ end
141
+ @thumb.make
142
+ end
143
+
144
+ should "create the thumbnail when sent #make" do
145
+ dst = @thumb.make
146
+ assert_match /100x50/, `identify "#{dst.path}"`
147
+ end
148
+
149
+ context "redefined to have bad source_file_options setting" do
150
+ setup do
151
+ @thumb = Paperclip::Thumbnail.new(@file,
152
+ :geometry => "100x50#",
153
+ :source_file_options => "-this-aint-no-option")
154
+ end
155
+
156
+ should "error when trying to create the thumbnail" do
157
+ assert_raises(Paperclip::PaperclipError) do
158
+ @thumb.make
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ context "being thumbnailed with convert options set" do
165
+ setup do
166
+ @thumb = Paperclip::Thumbnail.new(@file,
167
+ :geometry => "100x50#",
168
+ :convert_options => "-strip -depth 8")
169
+ end
170
+
171
+ should "have convert_options value set" do
172
+ assert_equal %w"-strip -depth 8", @thumb.convert_options
173
+ end
174
+
175
+ should "send the right command to convert when sent #make" do
176
+ Paperclip.expects(:run).with do |*arg|
177
+ arg[0] == 'convert' &&
178
+ arg[1] == ':source -resize "x50" -crop "100x50+114+0" +repage -strip -depth 8 :dest' &&
179
+ arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
180
+ end
181
+ @thumb.make
182
+ end
183
+
184
+ should "create the thumbnail when sent #make" do
185
+ dst = @thumb.make
186
+ assert_match /100x50/, `identify "#{dst.path}"`
187
+ end
188
+
189
+ context "redefined to have bad convert_options setting" do
190
+ setup do
191
+ @thumb = Paperclip::Thumbnail.new(@file,
192
+ :geometry => "100x50#",
193
+ :convert_options => "-this-aint-no-option")
194
+ end
195
+
196
+ should "error when trying to create the thumbnail" do
197
+ assert_raises(Paperclip::PaperclipError) do
198
+ @thumb.make
199
+ end
200
+ end
201
+
202
+ should "let us know when a command isn't found versus a processing error" do
203
+ old_path = ENV['PATH']
204
+ begin
205
+ ENV['PATH'] = ''
206
+ assert_raises(Paperclip::CommandNotFoundError) do
207
+ @thumb.make
208
+ end
209
+ ensure
210
+ ENV['PATH'] = old_path
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ context "being thumbnailed with a blank geometry string" do
217
+ setup do
218
+ @thumb = Paperclip::Thumbnail.new(@file,
219
+ :geometry => "",
220
+ :convert_options => "-gravity center -crop \"300x300+0-0\"")
221
+ end
222
+
223
+ should "not get resized by default" do
224
+ assert !@thumb.transformation_command.include?("-resize")
225
+ end
226
+ end
227
+
228
+ context "passing a custom file geometry parser" do
229
+ should "produce the appropriate transformation_command" do
230
+ GeoParser = Class.new do
231
+ def self.from_file(file)
232
+ new
233
+ end
234
+ def transformation_to(target, should_crop)
235
+ ["SCALE", "CROP"]
236
+ end
237
+ end
238
+
239
+ thumb = Paperclip::Thumbnail.new(@file, :geometry => '50x50', :file_geometry_parser => GeoParser)
240
+
241
+ transformation_command = thumb.transformation_command
242
+
243
+ assert transformation_command.include?('-crop'),
244
+ %{expected #{transformation_command.inspect} to include '-crop'}
245
+ assert transformation_command.include?('"CROP"'),
246
+ %{expected #{transformation_command.inspect} to include '"CROP"'}
247
+ assert transformation_command.include?('-resize'),
248
+ %{expected #{transformation_command.inspect} to include '-resize'}
249
+ assert transformation_command.include?('"SCALE"'),
250
+ %{expected #{transformation_command.inspect} to include '"SCALE"'}
251
+ end
252
+ end
253
+
254
+ context "passing a custom geometry string parser" do
255
+ should "produce the appropriate transformation_command" do
256
+ GeoParser = Class.new do
257
+ def self.parse(s)
258
+ new
259
+ end
260
+
261
+ def to_s
262
+ "151x167"
263
+ end
264
+ end
265
+
266
+ thumb = Paperclip::Thumbnail.new(@file, :geometry => '50x50', :string_geometry_parser => GeoParser)
267
+
268
+ transformation_command = thumb.transformation_command
269
+
270
+ assert transformation_command.include?('"151x167"'),
271
+ %{expected #{transformation_command.inspect} to include '151x167'}
272
+ end
273
+ end
274
+ end
275
+
276
+ context "A multipage PDF" do
277
+ setup do
278
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "twopage.pdf"), 'rb')
279
+ end
280
+
281
+ teardown { @file.close }
282
+
283
+ should "start with two pages with dimensions 612x792" do
284
+ cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
285
+ assert_equal "612x792"*2, `#{cmd}`.chomp
286
+ end
287
+
288
+ context "being thumbnailed at 100x100 with cropping" do
289
+ setup do
290
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => "100x100#", :format => :png)
291
+ end
292
+
293
+ should "report its correct current and target geometries" do
294
+ assert_equal "100x100#", @thumb.target_geometry.to_s
295
+ assert_equal "612x792", @thumb.current_geometry.to_s
296
+ end
297
+
298
+ should "report its correct format" do
299
+ assert_equal :png, @thumb.format
300
+ end
301
+
302
+ should "create the thumbnail when sent #make" do
303
+ dst = @thumb.make
304
+ assert_match /100x100/, `identify "#{dst.path}"`
305
+ end
306
+ end
307
+ end
308
+
309
+ context "An animated gif" do
310
+ setup do
311
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "animated.gif"), 'rb')
312
+ end
313
+
314
+ teardown { @file.close }
315
+
316
+ should "start with 12 frames with size 100x100" do
317
+ cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
318
+ assert_equal "100x100"*12, `#{cmd}`.chomp
319
+ end
320
+
321
+ context "with static output" do
322
+ setup do
323
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => "50x50", :format => :jpg)
324
+ end
325
+
326
+ should "create the single frame thumbnail when sent #make" do
327
+ dst = @thumb.make
328
+ cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
329
+ assert_equal "50x50", `#{cmd}`.chomp
330
+ end
331
+ end
332
+
333
+ context "with animated output format" do
334
+ setup do
335
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => "50x50", :format => :gif)
336
+ end
337
+
338
+ should "create the 12 frames thumbnail when sent #make" do
339
+ dst = @thumb.make
340
+ cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
341
+ assert_equal "50x50"*12, `#{cmd}`.chomp
342
+ end
343
+
344
+ should "use the -coalesce option" do
345
+ assert_equal @thumb.transformation_command.first, "-coalesce"
346
+ end
347
+ end
348
+
349
+ context "with omitted output format" do
350
+ setup do
351
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => "50x50")
352
+ end
353
+
354
+ should "create the 12 frames thumbnail when sent #make" do
355
+ dst = @thumb.make
356
+ cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
357
+ assert_equal "50x50"*12, `#{cmd}`.chomp
358
+ end
359
+
360
+ should "use the -coalesce option" do
361
+ assert_equal @thumb.transformation_command.first, "-coalesce"
362
+ end
363
+ end
364
+
365
+ context "with animated option set to false" do
366
+ setup do
367
+ @thumb = Paperclip::Thumbnail.new(@file, :geometry => "50x50", :animated => false)
368
+ end
369
+
370
+ should "output the gif format" do
371
+ dst = @thumb.make
372
+ cmd = %Q[identify "#{dst.path}"]
373
+ assert_match /GIF/, `#{cmd}`.chomp
374
+ end
375
+
376
+ should "create the single frame thumbnail when sent #make" do
377
+ dst = @thumb.make
378
+ cmd = %Q[identify -format "%wx%h" "#{dst.path}"]
379
+ assert_equal "50x50", `#{cmd}`.chomp
380
+ end
381
+ end
382
+ end
383
+ end