dm-paperclip 2.4.1 → 2.5.0

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