paperclip 2.1.2 → 2.1.5
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/{README → README.rdoc} +14 -3
- data/Rakefile +15 -5
- data/generators/paperclip/USAGE +1 -1
- data/generators/paperclip/paperclip_generator.rb +2 -2
- data/generators/paperclip/templates/{paperclip_migration.rb → paperclip_migration.rb.erb} +2 -0
- data/lib/paperclip.rb +64 -41
- data/lib/paperclip/attachment.rb +113 -35
- data/lib/paperclip/geometry.rb +17 -11
- data/lib/paperclip/iostream.rb +16 -1
- data/lib/paperclip/storage.rb +86 -11
- data/lib/paperclip/thumbnail.rb +19 -11
- data/lib/paperclip/upfile.rb +20 -5
- data/shoulda_macros/paperclip.rb +32 -0
- data/tasks/paperclip_tasks.rake +55 -14
- data/test/attachment_test.rb +455 -0
- data/test/database.yml +0 -1
- data/test/debug.log +0 -1745
- data/test/{test_geometry.rb → geometry_test.rb} +44 -18
- data/test/helper.rb +16 -0
- data/test/{test_integration.rb → integration_test.rb} +103 -25
- data/test/iostream_test.rb +68 -0
- data/test/paperclip_test.rb +186 -0
- data/test/s3.yml +0 -2
- data/test/{test_storage.rb → storage_test.rb} +41 -10
- data/test/{test_thumbnail.rb → thumbnail_test.rb} +45 -14
- metadata +50 -28
- data/test/test_attachment.rb +0 -230
- data/test/test_iostream.rb +0 -60
- data/test/test_paperclip.rb +0 -123
@@ -0,0 +1,455 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class Dummy
|
4
|
+
# This is a dummy class
|
5
|
+
end
|
6
|
+
|
7
|
+
class AttachmentTest < Test::Unit::TestCase
|
8
|
+
context "Attachment default_options" do
|
9
|
+
setup do
|
10
|
+
rebuild_model
|
11
|
+
@old_default_options = Paperclip::Attachment.default_options.dup
|
12
|
+
@new_default_options = @old_default_options.merge({
|
13
|
+
:path => "argle/bargle",
|
14
|
+
:url => "fooferon",
|
15
|
+
:default_url => "not here.png"
|
16
|
+
})
|
17
|
+
end
|
18
|
+
|
19
|
+
teardown do
|
20
|
+
Paperclip::Attachment.default_options.merge! @old_default_options
|
21
|
+
end
|
22
|
+
|
23
|
+
should "be overrideable" do
|
24
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
25
|
+
@new_default_options.keys.each do |key|
|
26
|
+
assert_equal @new_default_options[key],
|
27
|
+
Paperclip::Attachment.default_options[key]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "without an Attachment" do
|
32
|
+
setup do
|
33
|
+
@dummy = Dummy.new
|
34
|
+
end
|
35
|
+
|
36
|
+
should "return false when asked exists?" do
|
37
|
+
assert !@dummy.avatar.exists?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "on an Attachment" do
|
42
|
+
setup do
|
43
|
+
@dummy = Dummy.new
|
44
|
+
@attachment = @dummy.avatar
|
45
|
+
end
|
46
|
+
|
47
|
+
Paperclip::Attachment.default_options.keys.each do |key|
|
48
|
+
should "be the default_options for #{key}" do
|
49
|
+
assert_equal @old_default_options[key],
|
50
|
+
@attachment.instance_variable_get("@#{key}"),
|
51
|
+
key
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when redefined" do
|
56
|
+
setup do
|
57
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
58
|
+
@dummy = Dummy.new
|
59
|
+
@attachment = @dummy.avatar
|
60
|
+
end
|
61
|
+
|
62
|
+
Paperclip::Attachment.default_options.keys.each do |key|
|
63
|
+
should "be the new default_options for #{key}" do
|
64
|
+
assert_equal @new_default_options[key],
|
65
|
+
@attachment.instance_variable_get("@#{key}"),
|
66
|
+
key
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "An attachment with similarly named interpolations" do
|
74
|
+
setup do
|
75
|
+
rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
|
76
|
+
@dummy = Dummy.new
|
77
|
+
@dummy.stubs(:id).returns(1024)
|
78
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
79
|
+
"fixtures",
|
80
|
+
"5k.png"), 'rb')
|
81
|
+
@dummy.avatar = @file
|
82
|
+
end
|
83
|
+
|
84
|
+
should "make sure that they are interpolated correctly" do
|
85
|
+
assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "An attachment with a :rails_env interpolation" do
|
90
|
+
setup do
|
91
|
+
@rails_env = "blah"
|
92
|
+
@id = 1024
|
93
|
+
rebuild_model :path => ":rails_env/:id.png"
|
94
|
+
@dummy = Dummy.new
|
95
|
+
@dummy.stubs(:id).returns(@id)
|
96
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
97
|
+
"fixtures",
|
98
|
+
"5k.png"), 'rb')
|
99
|
+
@dummy.avatar = @file
|
100
|
+
end
|
101
|
+
|
102
|
+
should "return the proper path" do
|
103
|
+
temporary_rails_env(@rails_env) {
|
104
|
+
assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
|
105
|
+
}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "An attachment with :convert_options" do
|
110
|
+
setup do
|
111
|
+
rebuild_model :styles => {
|
112
|
+
:thumb => "100x100",
|
113
|
+
:large => "400x400"
|
114
|
+
},
|
115
|
+
:convert_options => {
|
116
|
+
:all => "-do_stuff",
|
117
|
+
:thumb => "-thumbnailize"
|
118
|
+
}
|
119
|
+
@dummy = Dummy.new
|
120
|
+
end
|
121
|
+
|
122
|
+
should "report the correct options when sent #extra_options_for(:thumb)" do
|
123
|
+
assert_equal "-thumbnailize -do_stuff", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
|
124
|
+
end
|
125
|
+
|
126
|
+
should "report the correct options when sent #extra_options_for(:large)" do
|
127
|
+
assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when given a file" do
|
131
|
+
setup do
|
132
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
133
|
+
"fixtures",
|
134
|
+
"5k.png"), 'rb')
|
135
|
+
Paperclip::Thumbnail.stubs(:make)
|
136
|
+
[:thumb, :large].each do |style|
|
137
|
+
@dummy.avatar.stubs(:extra_options_for).with(style)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
[:thumb, :large].each do |style|
|
142
|
+
should "call extra_options_for(#{style})" do
|
143
|
+
@dummy.avatar.expects(:extra_options_for).with(style)
|
144
|
+
@dummy.avatar = @file
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "Assigning an attachment" do
|
151
|
+
setup do
|
152
|
+
rebuild_model
|
153
|
+
|
154
|
+
@not_file = mock
|
155
|
+
@not_file.stubs(:nil?).returns(false)
|
156
|
+
@not_file.expects(:to_tempfile).returns(self)
|
157
|
+
@not_file.expects(:original_filename).returns("filename.png\r\n")
|
158
|
+
@not_file.expects(:content_type).returns("image/png\r\n")
|
159
|
+
@not_file.expects(:size).returns(10).times(2)
|
160
|
+
|
161
|
+
@dummy = Dummy.new
|
162
|
+
@attachment = @dummy.avatar
|
163
|
+
@attachment.expects(:valid_assignment?).with(@not_file).returns(true)
|
164
|
+
@attachment.expects(:queue_existing_for_delete)
|
165
|
+
@attachment.expects(:post_process)
|
166
|
+
@attachment.expects(:validate)
|
167
|
+
@dummy.avatar = @not_file
|
168
|
+
end
|
169
|
+
|
170
|
+
should "strip whitespace from original_filename field" do
|
171
|
+
assert_equal "filename.png", @dummy.avatar.original_filename
|
172
|
+
end
|
173
|
+
|
174
|
+
should "strip whitespace from content_type field" do
|
175
|
+
assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "Attachment with strange letters" do
|
180
|
+
setup do
|
181
|
+
rebuild_model
|
182
|
+
|
183
|
+
@not_file = mock
|
184
|
+
@not_file.stubs(:nil?).returns(false)
|
185
|
+
@not_file.expects(:to_tempfile).returns(self)
|
186
|
+
@not_file.expects(:original_filename).returns("sheep_say_bæ.png\r\n")
|
187
|
+
@not_file.expects(:content_type).returns("image/png\r\n")
|
188
|
+
@not_file.expects(:size).returns(10).times(2)
|
189
|
+
|
190
|
+
@dummy = Dummy.new
|
191
|
+
@attachment = @dummy.avatar
|
192
|
+
@attachment.expects(:valid_assignment?).with(@not_file).returns(true)
|
193
|
+
@attachment.expects(:queue_existing_for_delete)
|
194
|
+
@attachment.expects(:post_process)
|
195
|
+
@attachment.expects(:validate)
|
196
|
+
@dummy.avatar = @not_file
|
197
|
+
end
|
198
|
+
|
199
|
+
should "remove strange letters and replace with underscore (_)" do
|
200
|
+
assert_equal "sheep_say_b_.png", @dummy.avatar.original_filename
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
context "An attachment" do
|
206
|
+
setup do
|
207
|
+
Paperclip::Attachment.default_options.merge!({
|
208
|
+
:path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
|
209
|
+
})
|
210
|
+
FileUtils.rm_rf("tmp")
|
211
|
+
rebuild_model
|
212
|
+
@instance = Dummy.new
|
213
|
+
@attachment = Paperclip::Attachment.new(:avatar, @instance)
|
214
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
215
|
+
"fixtures",
|
216
|
+
"5k.png"), 'rb')
|
217
|
+
end
|
218
|
+
|
219
|
+
should "raise if there are not the correct columns when you try to assign" do
|
220
|
+
@other_attachment = Paperclip::Attachment.new(:not_here, @instance)
|
221
|
+
assert_raises(Paperclip::PaperclipError) do
|
222
|
+
@other_attachment.assign(@file)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
should "return its default_url when no file assigned" do
|
227
|
+
assert @attachment.to_file.nil?
|
228
|
+
assert_equal "/avatars/original/missing.png", @attachment.url
|
229
|
+
assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
|
230
|
+
end
|
231
|
+
|
232
|
+
should "return nil as path when no file assigned" do
|
233
|
+
assert @attachment.to_file.nil?
|
234
|
+
assert_equal nil, @attachment.path
|
235
|
+
assert_equal nil, @attachment.path(:blah)
|
236
|
+
end
|
237
|
+
|
238
|
+
context "with a file assigned in the database" do
|
239
|
+
setup do
|
240
|
+
@attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
|
241
|
+
@attachment.stubs(:instance_read).with(:content_type).returns("image/png")
|
242
|
+
@attachment.stubs(:instance_read).with(:file_size).returns(12345)
|
243
|
+
now = Time.now
|
244
|
+
Time.stubs(:now).returns(now)
|
245
|
+
@attachment.stubs(:instance_read).with(:updated_at).returns(Time.now)
|
246
|
+
end
|
247
|
+
|
248
|
+
should "return a correct url even if the file does not exist" do
|
249
|
+
assert_nil @attachment.to_file
|
250
|
+
assert_match %r{^/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
|
251
|
+
end
|
252
|
+
|
253
|
+
should "make sure the updated_at mtime is in the url if it is defined" do
|
254
|
+
assert_match %r{#{Time.now.to_i}$}, @attachment.url(:blah)
|
255
|
+
end
|
256
|
+
|
257
|
+
context "with the updated_at field removed" do
|
258
|
+
setup do
|
259
|
+
@attachment.stubs(:instance_read).with(:updated_at).returns(nil)
|
260
|
+
end
|
261
|
+
|
262
|
+
should "only return the url without the updated_at when sent #url" do
|
263
|
+
assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
should "return the proper path when filename has a single .'s" do
|
268
|
+
assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png", @attachment.path
|
269
|
+
end
|
270
|
+
|
271
|
+
should "return the proper path when filename has multiple .'s" do
|
272
|
+
@attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
|
273
|
+
assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png", @attachment.path
|
274
|
+
end
|
275
|
+
|
276
|
+
context "when expecting three styles" do
|
277
|
+
setup do
|
278
|
+
styles = {:styles => { :large => ["400x400", :png],
|
279
|
+
:medium => ["100x100", :gif],
|
280
|
+
:small => ["32x32#", :jpg]}}
|
281
|
+
@attachment = Paperclip::Attachment.new(:avatar,
|
282
|
+
@instance,
|
283
|
+
styles)
|
284
|
+
end
|
285
|
+
|
286
|
+
context "and assigned a file" do
|
287
|
+
setup do
|
288
|
+
now = Time.now
|
289
|
+
Time.stubs(:now).returns(now)
|
290
|
+
@attachment.assign(@file)
|
291
|
+
end
|
292
|
+
|
293
|
+
should "be dirty" do
|
294
|
+
assert @attachment.dirty?
|
295
|
+
end
|
296
|
+
|
297
|
+
context "and saved" do
|
298
|
+
setup do
|
299
|
+
@attachment.save
|
300
|
+
end
|
301
|
+
|
302
|
+
should "return the real url" do
|
303
|
+
file = @attachment.to_file
|
304
|
+
assert file
|
305
|
+
assert_match %r{^/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
|
306
|
+
assert_match %r{^/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
|
307
|
+
file.close
|
308
|
+
end
|
309
|
+
|
310
|
+
should "commit the files to disk" do
|
311
|
+
[:large, :medium, :small].each do |style|
|
312
|
+
io = @attachment.to_io(style)
|
313
|
+
assert File.exists?(io)
|
314
|
+
assert ! io.is_a?(::Tempfile)
|
315
|
+
io.close
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
should "save the files as the right formats and sizes" do
|
320
|
+
[[:large, 400, 61, "PNG"],
|
321
|
+
[:medium, 100, 15, "GIF"],
|
322
|
+
[:small, 32, 32, "JPEG"]].each do |style|
|
323
|
+
cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
|
324
|
+
out = `#{cmd}`
|
325
|
+
width, height, size, format = out.split(" ")
|
326
|
+
assert_equal style[1].to_s, width.to_s
|
327
|
+
assert_equal style[2].to_s, height.to_s
|
328
|
+
assert_equal style[3].to_s, format.to_s
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
should "still have its #file attribute not be nil" do
|
333
|
+
assert ! (file = @attachment.to_file).nil?
|
334
|
+
file.close
|
335
|
+
end
|
336
|
+
|
337
|
+
context "and deleted" do
|
338
|
+
setup do
|
339
|
+
@existing_names = @attachment.styles.keys.collect do |style|
|
340
|
+
@attachment.path(style)
|
341
|
+
end
|
342
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
343
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
344
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
345
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
346
|
+
@attachment.assign nil
|
347
|
+
@attachment.save
|
348
|
+
end
|
349
|
+
|
350
|
+
should "delete the files" do
|
351
|
+
@existing_names.each{|f| assert ! File.exists?(f) }
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
|
360
|
+
context "when trying a nonexistant storage type" do
|
361
|
+
setup do
|
362
|
+
rebuild_model :storage => :not_here
|
363
|
+
end
|
364
|
+
|
365
|
+
should "not be able to find the module" do
|
366
|
+
assert_raise(NameError){ Dummy.new.avatar }
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
context "An attachment with only a avatar_file_name column" do
|
372
|
+
setup do
|
373
|
+
ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
|
374
|
+
table.column :avatar_file_name, :string
|
375
|
+
end
|
376
|
+
rebuild_class
|
377
|
+
@dummy = Dummy.new
|
378
|
+
@file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
|
379
|
+
end
|
380
|
+
|
381
|
+
should "not error when assigned an attachment" do
|
382
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
383
|
+
end
|
384
|
+
|
385
|
+
should "return nil when sent #avatar_updated_at" do
|
386
|
+
@dummy.avatar = @file
|
387
|
+
assert_nil @dummy.avatar.updated_at
|
388
|
+
end
|
389
|
+
|
390
|
+
should "return the right value when sent #avatar_file_size" do
|
391
|
+
@dummy.avatar = @file
|
392
|
+
assert_equal @file.size, @dummy.avatar.size
|
393
|
+
end
|
394
|
+
|
395
|
+
context "and avatar_updated_at column" do
|
396
|
+
setup do
|
397
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
|
398
|
+
rebuild_class
|
399
|
+
@dummy = Dummy.new
|
400
|
+
end
|
401
|
+
|
402
|
+
should "not error when assigned an attachment" do
|
403
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
404
|
+
end
|
405
|
+
|
406
|
+
should "return the right value when sent #avatar_updated_at" do
|
407
|
+
now = Time.now
|
408
|
+
Time.stubs(:now).returns(now)
|
409
|
+
@dummy.avatar = @file
|
410
|
+
assert_equal now.to_i, @dummy.avatar.updated_at
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
context "and avatar_content_type column" do
|
415
|
+
setup do
|
416
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
|
417
|
+
rebuild_class
|
418
|
+
@dummy = Dummy.new
|
419
|
+
end
|
420
|
+
|
421
|
+
should "not error when assigned an attachment" do
|
422
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
423
|
+
end
|
424
|
+
|
425
|
+
should "return the right value when sent #avatar_content_type" do
|
426
|
+
@dummy.avatar = @file
|
427
|
+
assert_equal "image/png", @dummy.avatar.content_type
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context "and avatar_file_size column" do
|
432
|
+
setup do
|
433
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
|
434
|
+
rebuild_class
|
435
|
+
@dummy = Dummy.new
|
436
|
+
end
|
437
|
+
|
438
|
+
should "not error when assigned an attachment" do
|
439
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
440
|
+
end
|
441
|
+
|
442
|
+
should "return the right value when sent #avatar_file_size" do
|
443
|
+
@dummy.avatar = @file
|
444
|
+
assert_equal @file.size, @dummy.avatar.size
|
445
|
+
end
|
446
|
+
|
447
|
+
should "return the right value when saved, reloaded, and sent #avatar_file_size" do
|
448
|
+
@dummy.avatar = @file
|
449
|
+
@dummy.save
|
450
|
+
@dummy = Dummy.find(@dummy.id)
|
451
|
+
assert_equal @file.size, @dummy.avatar.size
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|