rsturim-paperclip 2.2.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/LICENSE +26 -0
  2. data/README.rdoc +174 -0
  3. data/Rakefile +99 -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 +1 -0
  8. data/lib/paperclip.rb +350 -0
  9. data/lib/paperclip/attachment.rb +413 -0
  10. data/lib/paperclip/callback_compatability.rb +33 -0
  11. data/lib/paperclip/geometry.rb +115 -0
  12. data/lib/paperclip/interpolations.rb +105 -0
  13. data/lib/paperclip/iostream.rb +58 -0
  14. data/lib/paperclip/matchers.rb +4 -0
  15. data/lib/paperclip/matchers/have_attached_file_matcher.rb +49 -0
  16. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +66 -0
  17. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +48 -0
  18. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +83 -0
  19. data/lib/paperclip/processor.rb +49 -0
  20. data/lib/paperclip/storage.rb +241 -0
  21. data/lib/paperclip/thumbnail.rb +70 -0
  22. data/lib/paperclip/upfile.rb +48 -0
  23. data/shoulda_macros/paperclip.rb +68 -0
  24. data/tasks/paperclip_tasks.rake +79 -0
  25. data/test/attachment_test.rb +768 -0
  26. data/test/database.yml +4 -0
  27. data/test/fixtures/12k.png +0 -0
  28. data/test/fixtures/50x50.png +0 -0
  29. data/test/fixtures/5k.png +0 -0
  30. data/test/fixtures/bad.png +1 -0
  31. data/test/fixtures/s3.yml +4 -0
  32. data/test/fixtures/text.txt +0 -0
  33. data/test/fixtures/twopage.pdf +0 -0
  34. data/test/geometry_test.rb +177 -0
  35. data/test/helper.rb +100 -0
  36. data/test/integration_test.rb +481 -0
  37. data/test/interpolations_test.rb +120 -0
  38. data/test/iostream_test.rb +71 -0
  39. data/test/matchers/have_attached_file_matcher_test.rb +21 -0
  40. data/test/matchers/validate_attachment_content_type_matcher_test.rb +30 -0
  41. data/test/matchers/validate_attachment_presence_matcher_test.rb +21 -0
  42. data/test/matchers/validate_attachment_size_matcher_test.rb +50 -0
  43. data/test/paperclip_test.rb +291 -0
  44. data/test/processor_test.rb +10 -0
  45. data/test/storage_test.rb +293 -0
  46. data/test/thumbnail_test.rb +177 -0
  47. metadata +124 -0
@@ -0,0 +1,768 @@
1
+ require 'test/helper'
2
+
3
+ class Dummy
4
+ # This is a dummy class
5
+ end
6
+
7
+ class AttachmentTest < Test::Unit::TestCase
8
+ should "return the path based on the url by default" do
9
+ @attachment = attachment :url => "/:class/:id/:basename"
10
+ @model = @attachment.instance
11
+ @model.id = 1234
12
+ @model.avatar_file_name = "fake.jpg"
13
+ assert_equal "#{RAILS_ROOT}/public/fake_models/1234/fake", @attachment.path
14
+ end
15
+
16
+ context "Attachment default_options" do
17
+ setup do
18
+ rebuild_model
19
+ @old_default_options = Paperclip::Attachment.default_options.dup
20
+ @new_default_options = @old_default_options.merge({
21
+ :path => "argle/bargle",
22
+ :url => "fooferon",
23
+ :default_url => "not here.png"
24
+ })
25
+ end
26
+
27
+ teardown do
28
+ Paperclip::Attachment.default_options.merge! @old_default_options
29
+ end
30
+
31
+ should "be overrideable" do
32
+ Paperclip::Attachment.default_options.merge!(@new_default_options)
33
+ @new_default_options.keys.each do |key|
34
+ assert_equal @new_default_options[key],
35
+ Paperclip::Attachment.default_options[key]
36
+ end
37
+ end
38
+
39
+ context "without an Attachment" do
40
+ setup do
41
+ @dummy = Dummy.new
42
+ end
43
+
44
+ should "return false when asked exists?" do
45
+ assert !@dummy.avatar.exists?
46
+ end
47
+ end
48
+
49
+ context "on an Attachment" do
50
+ setup do
51
+ @dummy = Dummy.new
52
+ @attachment = @dummy.avatar
53
+ end
54
+
55
+ Paperclip::Attachment.default_options.keys.each do |key|
56
+ should "be the default_options for #{key}" do
57
+ assert_equal @old_default_options[key],
58
+ @attachment.instance_variable_get("@#{key}"),
59
+ key
60
+ end
61
+ end
62
+
63
+ context "when redefined" do
64
+ setup do
65
+ Paperclip::Attachment.default_options.merge!(@new_default_options)
66
+ @dummy = Dummy.new
67
+ @attachment = @dummy.avatar
68
+ end
69
+
70
+ Paperclip::Attachment.default_options.keys.each do |key|
71
+ should "be the new default_options for #{key}" do
72
+ assert_equal @new_default_options[key],
73
+ @attachment.instance_variable_get("@#{key}"),
74
+ key
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ context "An attachment with similarly named interpolations" do
82
+ setup do
83
+ rebuild_model :path => ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
84
+ @dummy = Dummy.new
85
+ @dummy.stubs(:id).returns(1024)
86
+ @file = File.new(File.join(File.dirname(__FILE__),
87
+ "fixtures",
88
+ "5k.png"), 'rb')
89
+ @dummy.avatar = @file
90
+ end
91
+
92
+ teardown { @file.close }
93
+
94
+ should "make sure that they are interpolated correctly" do
95
+ assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
96
+ end
97
+ end
98
+
99
+ context "An attachment with a :rails_env interpolation" do
100
+ setup do
101
+ @rails_env = "blah"
102
+ @id = 1024
103
+ rebuild_model :path => ":rails_env/:id.png"
104
+ @dummy = Dummy.new
105
+ @dummy.stubs(:id).returns(@id)
106
+ @file = StringIO.new(".")
107
+ @dummy.avatar = @file
108
+ end
109
+
110
+ should "return the proper path" do
111
+ temporary_rails_env(@rails_env) {
112
+ assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
113
+ }
114
+ end
115
+ end
116
+
117
+ context "An attachment with a default style and an extension interpolation" do
118
+ setup do
119
+ @attachment = attachment :path => ":basename.:extension",
120
+ :styles => { :default => ["100x100", :png] },
121
+ :default_style => :default
122
+ @file = StringIO.new("...")
123
+ @file.expects(:original_filename).returns("file.jpg")
124
+ end
125
+ should "return the right extension for the path" do
126
+ @attachment.assign(@file)
127
+ assert_equal "file.png", @attachment.path
128
+ end
129
+ end
130
+
131
+ context "An attachment with :convert_options" do
132
+ setup do
133
+ rebuild_model :styles => {
134
+ :thumb => "100x100",
135
+ :large => "400x400"
136
+ },
137
+ :convert_options => {
138
+ :all => "-do_stuff",
139
+ :thumb => "-thumbnailize"
140
+ }
141
+ @dummy = Dummy.new
142
+ @dummy.avatar
143
+ end
144
+
145
+ should "report the correct options when sent #extra_options_for(:thumb)" do
146
+ assert_equal "-thumbnailize -do_stuff", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
147
+ end
148
+
149
+ should "report the correct options when sent #extra_options_for(:large)" do
150
+ assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
151
+ end
152
+
153
+ before_should "call extra_options_for(:thumb/:large)" do
154
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
155
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
156
+ end
157
+ end
158
+
159
+ context "An attachment with :convert_options that is a proc" do
160
+ setup do
161
+ rebuild_model :styles => {
162
+ :thumb => "100x100",
163
+ :large => "400x400"
164
+ },
165
+ :convert_options => {
166
+ :all => lambda{|i| i.all },
167
+ :thumb => lambda{|i| i.thumb }
168
+ }
169
+ Dummy.class_eval do
170
+ def all; "-all"; end
171
+ def thumb; "-thumb"; end
172
+ end
173
+ @dummy = Dummy.new
174
+ @dummy.avatar
175
+ end
176
+
177
+ should "report the correct options when sent #extra_options_for(:thumb)" do
178
+ assert_equal "-thumb -all", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
179
+ end
180
+
181
+ should "report the correct options when sent #extra_options_for(:large)" do
182
+ assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
183
+ end
184
+
185
+ before_should "call extra_options_for(:thumb/:large)" do
186
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
187
+ Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
188
+ end
189
+ end
190
+
191
+ context "An attachment with :path that is a proc" do
192
+ setup do
193
+ rebuild_model :path => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
194
+
195
+ @file = File.new(File.join(File.dirname(__FILE__),
196
+ "fixtures",
197
+ "5k.png"), 'rb')
198
+ @dummyA = Dummy.new(:other => 'a')
199
+ @dummyA.avatar = @file
200
+ @dummyB = Dummy.new(:other => 'b')
201
+ @dummyB.avatar = @file
202
+ end
203
+
204
+ teardown { @file.close }
205
+
206
+ should "return correct path" do
207
+ assert_equal "path/a.png", @dummyA.avatar.path
208
+ assert_equal "path/b.png", @dummyB.avatar.path
209
+ end
210
+ end
211
+
212
+ context "An attachment with :styles that is a proc" do
213
+ setup do
214
+ rebuild_model :styles => lambda{ |attachment| {:thumb => "50x50#", :large => "400x400"} }
215
+
216
+ @attachment = Dummy.new.avatar
217
+ end
218
+
219
+ should "have the correct geometry" do
220
+ assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
221
+ end
222
+ end
223
+
224
+ context "An attachment with :url that is a proc" do
225
+ setup do
226
+ rebuild_model :url => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
227
+
228
+ @file = File.new(File.join(File.dirname(__FILE__),
229
+ "fixtures",
230
+ "5k.png"), 'rb')
231
+ @dummyA = Dummy.new(:other => 'a')
232
+ @dummyA.avatar = @file
233
+ @dummyB = Dummy.new(:other => 'b')
234
+ @dummyB.avatar = @file
235
+ end
236
+
237
+ teardown { @file.close }
238
+
239
+ should "return correct url" do
240
+ assert_equal "path/a.png", @dummyA.avatar.url(:original, false)
241
+ assert_equal "path/b.png", @dummyB.avatar.url(:original, false)
242
+ end
243
+ end
244
+
245
+ geometry_specs = [
246
+ [ lambda{|z| "50x50#" }, :png ],
247
+ lambda{|z| "50x50#" },
248
+ { :geometry => lambda{|z| "50x50#" } }
249
+ ]
250
+ geometry_specs.each do |geometry_spec|
251
+ context "An attachment geometry like #{geometry_spec}" do
252
+ setup do
253
+ rebuild_model :styles => { :normal => geometry_spec }
254
+ @attachment = Dummy.new.avatar
255
+ end
256
+
257
+ should "not run the procs immediately" do
258
+ assert_kind_of Proc, @attachment.styles[:normal][:geometry]
259
+ end
260
+
261
+ context "when assigned" do
262
+ setup do
263
+ @file = StringIO.new(".")
264
+ @attachment.assign(@file)
265
+ end
266
+
267
+ should "have the correct geometry" do
268
+ assert_equal "50x50#", @attachment.styles[:normal][:geometry]
269
+ end
270
+ end
271
+ end
272
+ end
273
+
274
+ context "An attachment with both 'normal' and hash-style styles" do
275
+ setup do
276
+ rebuild_model :styles => {
277
+ :normal => ["50x50#", :png],
278
+ :hash => { :geometry => "50x50#", :format => :png }
279
+ }
280
+ @dummy = Dummy.new
281
+ @attachment = @dummy.avatar
282
+ end
283
+
284
+ [:processors, :whiny, :convert_options, :geometry, :format].each do |field|
285
+ should "have the same #{field} field" do
286
+ assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
287
+ end
288
+ end
289
+ end
290
+
291
+ context "An attachment with :processors that is a proc" do
292
+ setup do
293
+ rebuild_model :styles => { :normal => '' }, :processors => lambda { |a| [ :test ] }
294
+ @attachment = Dummy.new.avatar
295
+ end
296
+
297
+ should "not run the proc immediately" do
298
+ assert_kind_of Proc, @attachment.styles[:normal][:processors]
299
+ end
300
+
301
+ context "when assigned" do
302
+ setup do
303
+ @attachment.assign(StringIO.new("."))
304
+ end
305
+
306
+ should "have the correct processors" do
307
+ assert_equal [ :test ], @attachment.styles[:normal][:processors]
308
+ end
309
+ end
310
+ end
311
+
312
+ context "An attachment with erroring processor" do
313
+ setup do
314
+ rebuild_model :processor => [:thumbnail], :styles => { :small => '' }, :whiny_thumbnails => true
315
+ @dummy = Dummy.new
316
+ Paperclip::Thumbnail.expects(:make).raises(Paperclip::PaperclipError, "cannot be processed.")
317
+ @file = StringIO.new("...")
318
+ @file.stubs(:to_tempfile).returns(@file)
319
+ @dummy.avatar = @file
320
+ end
321
+
322
+ should "correctly forward processing error message to the instance" do
323
+ @dummy.valid?
324
+ assert_contains @dummy.errors.full_messages, "Avatar cannot be processed."
325
+ end
326
+ end
327
+
328
+ context "An attachment with multiple processors" do
329
+ setup do
330
+ class Paperclip::Test < Paperclip::Processor; end
331
+ @style_params = { :once => {:one => 1, :two => 2} }
332
+ rebuild_model :processors => [:thumbnail, :test], :styles => @style_params
333
+ @dummy = Dummy.new
334
+ @file = StringIO.new("...")
335
+ @file.stubs(:to_tempfile).returns(@file)
336
+ Paperclip::Test.stubs(:make).returns(@file)
337
+ Paperclip::Thumbnail.stubs(:make).returns(@file)
338
+ end
339
+
340
+ context "when assigned" do
341
+ setup { @dummy.avatar = @file }
342
+
343
+ before_should "call #make on all specified processors" do
344
+ expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
345
+ Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
346
+ Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
347
+ end
348
+
349
+ before_should "call #make with attachment passed as third argument" do
350
+ expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
351
+ Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
352
+ end
353
+ end
354
+ end
355
+
356
+ context "An attachment with no processors defined" do
357
+ setup do
358
+ rebuild_model :processors => [], :styles => {:something => 1}
359
+ @dummy = Dummy.new
360
+ @file = StringIO.new("...")
361
+ end
362
+ should "raise when assigned to" do
363
+ assert_raises(RuntimeError){ @dummy.avatar = @file }
364
+ end
365
+ end
366
+
367
+ context "Assigning an attachment with post_process hooks" do
368
+ setup do
369
+ rebuild_model :styles => { :something => "100x100#" }
370
+ Dummy.class_eval do
371
+ before_avatar_post_process :do_before_avatar
372
+ after_avatar_post_process :do_after_avatar
373
+ before_post_process :do_before_all
374
+ after_post_process :do_after_all
375
+ def do_before_avatar; end
376
+ def do_after_avatar; end
377
+ def do_before_all; end
378
+ def do_after_all; end
379
+ end
380
+ @file = StringIO.new(".")
381
+ @file.stubs(:to_tempfile).returns(@file)
382
+ @dummy = Dummy.new
383
+ Paperclip::Thumbnail.stubs(:make).returns(@file)
384
+ @attachment = @dummy.avatar
385
+ end
386
+
387
+ should "call the defined callbacks when assigned" do
388
+ @dummy.expects(:do_before_avatar).with()
389
+ @dummy.expects(:do_after_avatar).with()
390
+ @dummy.expects(:do_before_all).with()
391
+ @dummy.expects(:do_after_all).with()
392
+ Paperclip::Thumbnail.expects(:make).returns(@file)
393
+ @dummy.avatar = @file
394
+ end
395
+
396
+ should "not cancel the processing if a before_post_process returns nil" do
397
+ @dummy.expects(:do_before_avatar).with().returns(nil)
398
+ @dummy.expects(:do_after_avatar).with()
399
+ @dummy.expects(:do_before_all).with().returns(nil)
400
+ @dummy.expects(:do_after_all).with()
401
+ Paperclip::Thumbnail.expects(:make).returns(@file)
402
+ @dummy.avatar = @file
403
+ end
404
+
405
+ should "cancel the processing if a before_post_process returns false" do
406
+ @dummy.expects(:do_before_avatar).never
407
+ @dummy.expects(:do_after_avatar).never
408
+ @dummy.expects(:do_before_all).with().returns(false)
409
+ @dummy.expects(:do_after_all).never
410
+ Paperclip::Thumbnail.expects(:make).never
411
+ @dummy.avatar = @file
412
+ end
413
+
414
+ should "cancel the processing if a before_avatar_post_process returns false" do
415
+ @dummy.expects(:do_before_avatar).with().returns(false)
416
+ @dummy.expects(:do_after_avatar).never
417
+ @dummy.expects(:do_before_all).with().returns(true)
418
+ @dummy.expects(:do_after_all).never
419
+ Paperclip::Thumbnail.expects(:make).never
420
+ @dummy.avatar = @file
421
+ end
422
+ end
423
+
424
+ context "Assigning an attachment" do
425
+ setup do
426
+ rebuild_model :styles => { :something => "100x100#" }
427
+ @file = StringIO.new(".")
428
+ @file.expects(:original_filename).returns("5k.png\n\n")
429
+ @file.expects(:content_type).returns("image/png\n\n")
430
+ @file.stubs(:to_tempfile).returns(@file)
431
+ @dummy = Dummy.new
432
+ Paperclip::Thumbnail.expects(:make).returns(@file)
433
+ @dummy.expects(:run_callbacks).with(:before_avatar_post_process, {:original => @file})
434
+ @dummy.expects(:run_callbacks).with(:before_post_process, {:original => @file})
435
+ @dummy.expects(:run_callbacks).with(:after_avatar_post_process, {:original => @file, :something => @file})
436
+ @dummy.expects(:run_callbacks).with(:after_post_process, {:original => @file, :something => @file})
437
+ @attachment = @dummy.avatar
438
+ @dummy.avatar = @file
439
+ end
440
+
441
+ should "strip whitespace from original_filename field" do
442
+ assert_equal "5k.png", @dummy.avatar.original_filename
443
+ end
444
+
445
+ should "strip whitespace from content_type field" do
446
+ assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
447
+ end
448
+ end
449
+
450
+ context "Attachment with strange letters" do
451
+ setup do
452
+ rebuild_model
453
+
454
+ @not_file = mock
455
+ @tempfile = mock
456
+ @not_file.stubs(:nil?).returns(false)
457
+ @not_file.expects(:size).returns(10)
458
+ @tempfile.expects(:size).returns(10)
459
+ @not_file.expects(:to_tempfile).returns(@tempfile)
460
+ @not_file.expects(:original_filename).returns("sheep_say_bæ.png\r\n")
461
+ @not_file.expects(:content_type).returns("image/png\r\n")
462
+
463
+ @dummy = Dummy.new
464
+ @attachment = @dummy.avatar
465
+ @attachment.expects(:valid_assignment?).with(@not_file).returns(true)
466
+ @attachment.expects(:queue_existing_for_delete)
467
+ @attachment.expects(:post_process)
468
+ @attachment.expects(:valid?).returns(true)
469
+ @attachment.expects(:validate)
470
+ @dummy.avatar = @not_file
471
+ end
472
+
473
+ should "remove strange letters and replace with underscore (_)" do
474
+ assert_equal "sheep_say_b_.png", @dummy.avatar.original_filename
475
+ end
476
+
477
+ end
478
+
479
+ context "An attachment" do
480
+ setup do
481
+ @old_defaults = Paperclip::Attachment.default_options.dup
482
+ Paperclip::Attachment.default_options.merge!({
483
+ :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
484
+ })
485
+ FileUtils.rm_rf("tmp")
486
+ rebuild_model
487
+ @instance = Dummy.new
488
+ @attachment = Paperclip::Attachment.new(:avatar, @instance)
489
+ @file = File.new(File.join(File.dirname(__FILE__),
490
+ "fixtures",
491
+ "5k.png"), 'rb')
492
+ end
493
+
494
+ teardown do
495
+ @file.close
496
+ Paperclip::Attachment.default_options.merge!(@old_defaults)
497
+ end
498
+
499
+ should "raise if there are not the correct columns when you try to assign" do
500
+ @other_attachment = Paperclip::Attachment.new(:not_here, @instance)
501
+ assert_raises(Paperclip::PaperclipError) do
502
+ @other_attachment.assign(@file)
503
+ end
504
+ end
505
+
506
+ should "return its default_url when no file assigned" do
507
+ assert @attachment.to_file.nil?
508
+ assert_equal "/avatars/original/missing.png", @attachment.url
509
+ assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
510
+ end
511
+
512
+ should "return nil as path when no file assigned" do
513
+ assert @attachment.to_file.nil?
514
+ assert_equal nil, @attachment.path
515
+ assert_equal nil, @attachment.path(:blah)
516
+ end
517
+
518
+ context "with a file assigned in the database" do
519
+ setup do
520
+ @attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
521
+ @attachment.stubs(:instance_read).with(:content_type).returns("image/png")
522
+ @attachment.stubs(:instance_read).with(:file_size).returns(12345)
523
+ now = Time.now
524
+ Time.stubs(:now).returns(now)
525
+ @attachment.stubs(:instance_read).with(:updated_at).returns(Time.now)
526
+ end
527
+
528
+ should "return a correct url even if the file does not exist" do
529
+ assert_nil @attachment.to_file
530
+ assert_match %r{^/system/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
531
+ end
532
+
533
+ should "make sure the updated_at mtime is in the url if it is defined" do
534
+ assert_match %r{#{Time.now.to_i}$}, @attachment.url(:blah)
535
+ end
536
+
537
+ should "make sure the updated_at mtime is NOT in the url if false is passed to the url method" do
538
+ assert_no_match %r{#{Time.now.to_i}$}, @attachment.url(:blah, false)
539
+ end
540
+
541
+ context "with the updated_at field removed" do
542
+ setup do
543
+ @attachment.stubs(:instance_read).with(:updated_at).returns(nil)
544
+ end
545
+
546
+ should "only return the url without the updated_at when sent #url" do
547
+ assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
548
+ end
549
+ end
550
+
551
+ should "return the proper path when filename has a single .'s" do
552
+ assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png", @attachment.path
553
+ end
554
+
555
+ should "return the proper path when filename has multiple .'s" do
556
+ @attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
557
+ assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png", @attachment.path
558
+ end
559
+
560
+ context "when expecting three styles" do
561
+ setup do
562
+ styles = {:styles => { :large => ["400x400", :png],
563
+ :medium => ["100x100", :gif],
564
+ :small => ["32x32#", :jpg]}}
565
+ @attachment = Paperclip::Attachment.new(:avatar,
566
+ @instance,
567
+ styles)
568
+ end
569
+
570
+ context "and assigned a file" do
571
+ setup do
572
+ now = Time.now
573
+ Time.stubs(:now).returns(now)
574
+ @attachment.assign(@file)
575
+ end
576
+
577
+ should "be dirty" do
578
+ assert @attachment.dirty?
579
+ end
580
+
581
+ context "and saved" do
582
+ setup do
583
+ @attachment.save
584
+ end
585
+
586
+ should "return the real url" do
587
+ file = @attachment.to_file
588
+ assert file
589
+ assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
590
+ assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
591
+ file.close
592
+ end
593
+
594
+ should "commit the files to disk" do
595
+ [:large, :medium, :small].each do |style|
596
+ io = @attachment.to_io(style)
597
+ assert File.exists?(io)
598
+ assert ! io.is_a?(::Tempfile)
599
+ io.close
600
+ end
601
+ end
602
+
603
+ should "save the files as the right formats and sizes" do
604
+ [[:large, 400, 61, "PNG"],
605
+ [:medium, 100, 15, "GIF"],
606
+ [:small, 32, 32, "JPEG"]].each do |style|
607
+ cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
608
+ out = `#{cmd}`
609
+ width, height, size, format = out.split(" ")
610
+ assert_equal style[1].to_s, width.to_s
611
+ assert_equal style[2].to_s, height.to_s
612
+ assert_equal style[3].to_s, format.to_s
613
+ end
614
+ end
615
+
616
+ should "still have its #file attribute not be nil" do
617
+ assert ! (file = @attachment.to_file).nil?
618
+ file.close
619
+ end
620
+
621
+ context "and trying to delete" do
622
+ setup do
623
+ @existing_names = @attachment.styles.keys.collect do |style|
624
+ @attachment.path(style)
625
+ end
626
+ end
627
+
628
+ should "delete the files after assigning nil" do
629
+ @attachment.expects(:instance_write).with(:file_name, nil)
630
+ @attachment.expects(:instance_write).with(:content_type, nil)
631
+ @attachment.expects(:instance_write).with(:file_size, nil)
632
+ @attachment.expects(:instance_write).with(:updated_at, nil)
633
+ @attachment.assign nil
634
+ @attachment.save
635
+ @existing_names.each{|f| assert ! File.exists?(f) }
636
+ end
637
+
638
+ should "delete the files when you call #clear and #save" do
639
+ @attachment.expects(:instance_write).with(:file_name, nil)
640
+ @attachment.expects(:instance_write).with(:content_type, nil)
641
+ @attachment.expects(:instance_write).with(:file_size, nil)
642
+ @attachment.expects(:instance_write).with(:updated_at, nil)
643
+ @attachment.clear
644
+ @attachment.save
645
+ @existing_names.each{|f| assert ! File.exists?(f) }
646
+ end
647
+
648
+ should "delete the files when you call #delete" do
649
+ @attachment.expects(:instance_write).with(:file_name, nil)
650
+ @attachment.expects(:instance_write).with(:content_type, nil)
651
+ @attachment.expects(:instance_write).with(:file_size, nil)
652
+ @attachment.expects(:instance_write).with(:updated_at, nil)
653
+ @attachment.destroy
654
+ @existing_names.each{|f| assert ! File.exists?(f) }
655
+ end
656
+ end
657
+ end
658
+ end
659
+ end
660
+
661
+ end
662
+
663
+ context "when trying a nonexistant storage type" do
664
+ setup do
665
+ rebuild_model :storage => :not_here
666
+ end
667
+
668
+ should "not be able to find the module" do
669
+ assert_raise(NameError){ Dummy.new.avatar }
670
+ end
671
+ end
672
+ end
673
+
674
+ context "An attachment with only a avatar_file_name column" do
675
+ setup do
676
+ ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
677
+ table.column :avatar_file_name, :string
678
+ end
679
+ rebuild_class
680
+ @dummy = Dummy.new
681
+ @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
682
+ end
683
+
684
+ teardown { @file.close }
685
+
686
+ should "not error when assigned an attachment" do
687
+ assert_nothing_raised { @dummy.avatar = @file }
688
+ end
689
+
690
+ should "return the time when sent #avatar_updated_at" do
691
+ now = Time.now
692
+ Time.stubs(:now).returns(now)
693
+ @dummy.avatar = @file
694
+ assert now, @dummy.avatar.updated_at
695
+ end
696
+
697
+ should "return nil when reloaded and sent #avatar_updated_at" do
698
+ @dummy.save
699
+ @dummy.reload
700
+ assert_nil @dummy.avatar.updated_at
701
+ end
702
+
703
+ should "return the right value when sent #avatar_file_size" do
704
+ @dummy.avatar = @file
705
+ assert_equal @file.size, @dummy.avatar.size
706
+ end
707
+
708
+ context "and avatar_updated_at column" do
709
+ setup do
710
+ ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
711
+ rebuild_class
712
+ @dummy = Dummy.new
713
+ end
714
+
715
+ should "not error when assigned an attachment" do
716
+ assert_nothing_raised { @dummy.avatar = @file }
717
+ end
718
+
719
+ should "return the right value when sent #avatar_updated_at" do
720
+ now = Time.now
721
+ Time.stubs(:now).returns(now)
722
+ @dummy.avatar = @file
723
+ assert_equal now.to_i, @dummy.avatar.updated_at
724
+ end
725
+ end
726
+
727
+ context "and avatar_content_type column" do
728
+ setup do
729
+ ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
730
+ rebuild_class
731
+ @dummy = Dummy.new
732
+ end
733
+
734
+ should "not error when assigned an attachment" do
735
+ assert_nothing_raised { @dummy.avatar = @file }
736
+ end
737
+
738
+ should "return the right value when sent #avatar_content_type" do
739
+ @dummy.avatar = @file
740
+ assert_equal "image/png", @dummy.avatar.content_type
741
+ end
742
+ end
743
+
744
+ context "and avatar_file_size column" do
745
+ setup do
746
+ ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
747
+ rebuild_class
748
+ @dummy = Dummy.new
749
+ end
750
+
751
+ should "not error when assigned an attachment" do
752
+ assert_nothing_raised { @dummy.avatar = @file }
753
+ end
754
+
755
+ should "return the right value when sent #avatar_file_size" do
756
+ @dummy.avatar = @file
757
+ assert_equal @file.size, @dummy.avatar.size
758
+ end
759
+
760
+ should "return the right value when saved, reloaded, and sent #avatar_file_size" do
761
+ @dummy.avatar = @file
762
+ @dummy.save
763
+ @dummy = Dummy.find(@dummy.id)
764
+ assert_equal @file.size, @dummy.avatar.size
765
+ end
766
+ end
767
+ end
768
+ end