paperclip 2.4.5 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Files changed (63) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +13 -0
  3. data/Appraisals +14 -0
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +5 -0
  6. data/NEWS +23 -0
  7. data/README.md +72 -42
  8. data/Rakefile +1 -46
  9. data/cucumber/paperclip_steps.rb +6 -0
  10. data/features/basic_integration.feature +46 -0
  11. data/features/rake_tasks.feature +63 -0
  12. data/features/step_definitions/attachment_steps.rb +65 -0
  13. data/features/step_definitions/html_steps.rb +15 -0
  14. data/features/step_definitions/rails_steps.rb +182 -0
  15. data/features/step_definitions/s3_steps.rb +14 -0
  16. data/features/step_definitions/web_steps.rb +209 -0
  17. data/features/support/env.rb +8 -0
  18. data/features/support/fakeweb.rb +3 -0
  19. data/features/support/fixtures/.boot_config.rb.swo +0 -0
  20. data/features/support/fixtures/boot_config.txt +15 -0
  21. data/features/support/fixtures/gemfile.txt +5 -0
  22. data/features/support/fixtures/preinitializer.txt +20 -0
  23. data/features/support/paths.rb +28 -0
  24. data/features/support/rails.rb +46 -0
  25. data/features/support/selectors.rb +19 -0
  26. data/gemfiles/rails2.gemfile +9 -0
  27. data/gemfiles/rails3.gemfile +9 -0
  28. data/gemfiles/rails3_1.gemfile +9 -0
  29. data/lib/paperclip.rb +26 -19
  30. data/lib/paperclip/attachment.rb +123 -109
  31. data/lib/paperclip/interpolations.rb +7 -4
  32. data/lib/paperclip/matchers.rb +33 -2
  33. data/lib/paperclip/missing_attachment_styles.rb +1 -1
  34. data/lib/paperclip/railtie.rb +5 -0
  35. data/lib/paperclip/schema.rb +39 -0
  36. data/lib/paperclip/storage/fog.rb +21 -10
  37. data/lib/paperclip/storage/s3.rb +107 -40
  38. data/lib/paperclip/style.rb +13 -5
  39. data/lib/paperclip/url_generator.rb +64 -0
  40. data/lib/paperclip/version.rb +1 -1
  41. data/lib/tasks/paperclip.rake +1 -1
  42. data/paperclip.gemspec +41 -0
  43. data/test/.gitignore +1 -0
  44. data/test/attachment_test.rb +155 -168
  45. data/test/fixtures/question?mark.png +0 -0
  46. data/test/helper.rb +24 -1
  47. data/test/interpolations_test.rb +16 -2
  48. data/test/paperclip_missing_attachment_styles_test.rb +16 -0
  49. data/test/paperclip_test.rb +72 -22
  50. data/test/schema_test.rb +98 -0
  51. data/test/storage/filesystem_test.rb +2 -2
  52. data/test/{fog_test.rb → storage/fog_test.rb} +35 -8
  53. data/test/storage/s3_live_test.rb +63 -13
  54. data/test/storage/s3_test.rb +394 -91
  55. data/test/style_test.rb +50 -21
  56. data/test/support/mock_attachment.rb +22 -0
  57. data/test/support/mock_interpolator.rb +24 -0
  58. data/test/support/mock_model.rb +2 -0
  59. data/test/support/mock_url_generator_builder.rb +27 -0
  60. data/test/url_generator_test.rb +187 -0
  61. metadata +307 -125
  62. data/lib/paperclip/options.rb +0 -78
  63. data/test/options_test.rb +0 -75
@@ -1,5 +1,5 @@
1
1
  require './test/helper'
2
- require 'aws/s3'
2
+ require 'aws'
3
3
 
4
4
  class S3Test < Test::Unit::TestCase
5
5
  def rails_env(env)
@@ -8,10 +8,17 @@ class S3Test < Test::Unit::TestCase
8
8
  end
9
9
  end
10
10
 
11
+ def setup
12
+ AWS.config(:access_key_id => "TESTKEY", :secret_access_key => "TESTSECRET", :stub_requests => true)
13
+ end
14
+
15
+ def teardown
16
+ AWS.config(:access_key_id => nil, :secret_access_key => nil, :stub_requests => nil)
17
+ end
18
+
11
19
  context "Parsing S3 credentials" do
12
20
  setup do
13
21
  @proxy_settings = {:host => "127.0.0.1", :port => 8888, :user => "foo", :password => "bar"}
14
- AWS::S3::Base.stubs(:establish_connection!)
15
22
  rebuild_model :storage => :s3,
16
23
  :bucket => "testing",
17
24
  :http_proxy => @proxy_settings,
@@ -51,9 +58,54 @@ class S3Test < Test::Unit::TestCase
51
58
 
52
59
  end
53
60
 
61
+ context ":bucket option via :s3_credentials" do
62
+
63
+ setup do
64
+ rebuild_model :storage => :s3, :s3_credentials => {:bucket => 'testing'}
65
+ @dummy = Dummy.new
66
+ end
67
+
68
+ should "populate #bucket_name" do
69
+ assert_equal @dummy.avatar.bucket_name, 'testing'
70
+ end
71
+
72
+ end
73
+
74
+ context ":bucket option" do
75
+
76
+ setup do
77
+ rebuild_model :storage => :s3, :bucket => "testing", :s3_credentials => {}
78
+ @dummy = Dummy.new
79
+ end
80
+
81
+ should "populate #bucket_name" do
82
+ assert_equal @dummy.avatar.bucket_name, 'testing'
83
+ end
84
+
85
+ end
86
+
87
+ context "missing :bucket option" do
88
+
89
+ setup do
90
+ rebuild_model :storage => :s3,
91
+ #:bucket => "testing", # intentionally left out
92
+ :http_proxy => @proxy_settings,
93
+ :s3_credentials => {:not => :important}
94
+
95
+ @dummy = Dummy.new
96
+ @dummy.avatar = StringIO.new(".")
97
+
98
+ end
99
+
100
+ should "raise an argument error" do
101
+ exception = assert_raise(ArgumentError) { @dummy.save }
102
+ assert_match /missing required :bucket option/, exception.message
103
+ end
104
+
105
+ end
106
+
54
107
  context "" do
55
108
  setup do
56
- AWS::S3::Base.stubs(:establish_connection!)
57
109
  rebuild_model :storage => :s3,
58
110
  :s3_credentials => {},
59
111
  :bucket => "bucket",
@@ -66,11 +118,46 @@ class S3Test < Test::Unit::TestCase
66
118
  should "return a url based on an S3 path" do
67
119
  assert_match %r{^http://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
68
120
  end
121
+
122
+ should "use the correct bucket" do
123
+ assert_equal "bucket", @dummy.avatar.s3_bucket.name
124
+ end
125
+
126
+ should "use the correct key" do
127
+ assert_equal "avatars/stringio.txt", @dummy.avatar.s3_object.key
128
+ end
129
+
130
+ end
131
+
132
+ context "An attachment that uses S3 for storage and has the style in the path" do
133
+ setup do
134
+ rebuild_model :storage => :s3,
135
+ :bucket => "testing",
136
+ :path => ":attachment/:style/:basename.:extension",
137
+ :styles => {
138
+ :thumb => "80x80>"
139
+ },
140
+ :s3_credentials => {
141
+ 'access_key_id' => "12345",
142
+ 'secret_access_key' => "54321"
143
+ }
144
+
145
+ @dummy = Dummy.new
146
+ @dummy.avatar = StringIO.new(".")
147
+ @avatar = @dummy.avatar
148
+ end
149
+
150
+ should "use an S3 object based on the correct path for the default style" do
151
+ assert_equal("avatars/original/stringio.txt", @dummy.avatar.s3_object.key)
152
+ end
153
+
154
+ should "use an S3 object based on the correct path for the custom style" do
155
+ assert_equal("avatars/thumb/stringio.txt", @dummy.avatar.s3_object(:thumb).key)
156
+ end
69
157
  end
70
158
 
71
159
  context "s3_host_name" do
72
160
  setup do
73
- AWS::S3::Base.stubs(:establish_connection!)
74
161
  rebuild_model :storage => :s3,
75
162
  :s3_credentials => {},
76
163
  :bucket => "bucket",
@@ -83,11 +170,14 @@ class S3Test < Test::Unit::TestCase
83
170
  should "return a url based on an :s3_host_name path" do
84
171
  assert_match %r{^http://s3-ap-northeast-1.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
85
172
  end
173
+
174
+ should "use the S3 bucket with the correct host name" do
175
+ assert_equal "s3-ap-northeast-1.amazonaws.com", @dummy.avatar.s3_bucket.config.s3_endpoint
176
+ end
86
177
  end
87
178
 
88
179
  context "An attachment that uses S3 for storage and has styles that return different file types" do
89
180
  setup do
90
- AWS::S3::Base.stubs(:establish_connection!)
91
181
  rebuild_model :styles => { :large => ['500x500#', :jpg] },
92
182
  :storage => :s3,
93
183
  :bucket => "bucket",
@@ -98,21 +188,28 @@ class S3Test < Test::Unit::TestCase
98
188
  }
99
189
 
100
190
  @dummy = Dummy.new
101
- @dummy.avatar = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
191
+ @dummy.avatar = File.new(fixture_file('5k.png'), 'rb')
102
192
  end
103
193
 
104
194
  should "return a url containing the correct original file mime type" do
105
195
  assert_match /.+\/5k.png/, @dummy.avatar.url
106
196
  end
107
197
 
198
+ should 'use the correct key for the original file mime type' do
199
+ assert_match /.+\/5k.png/, @dummy.avatar.s3_object.key
200
+ end
201
+
108
202
  should "return a url containing the correct processed file mime type" do
109
203
  assert_match /.+\/5k.jpg/, @dummy.avatar.url(:large)
110
204
  end
205
+
206
+ should "use the correct key for the processed file mime type" do
207
+ assert_match /.+\/5k.jpg/, @dummy.avatar.s3_object(:large).key
208
+ end
111
209
  end
112
210
 
113
211
  context "An attachment that uses S3 for storage and has spaces in file name" do
114
212
  setup do
115
- AWS::S3::Base.stubs(:establish_connection!)
116
213
  rebuild_model :styles => { :large => ['500x500#', :jpg] },
117
214
  :storage => :s3,
118
215
  :bucket => "bucket",
@@ -122,7 +219,7 @@ class S3Test < Test::Unit::TestCase
122
219
  }
123
220
 
124
221
  @dummy = Dummy.new
125
- @dummy.avatar = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', 'spaced file.png'), 'rb')
222
+ @dummy.avatar = File.new(fixture_file('spaced file.png'), 'rb')
126
223
  end
127
224
 
128
225
  should "return an unescaped version for path" do
@@ -136,7 +233,6 @@ class S3Test < Test::Unit::TestCase
136
233
 
137
234
  context "" do
138
235
  setup do
139
- AWS::S3::Base.stubs(:establish_connection!)
140
236
  rebuild_model :storage => :s3,
141
237
  :s3_credentials => {},
142
238
  :bucket => "bucket",
@@ -153,7 +249,6 @@ class S3Test < Test::Unit::TestCase
153
249
 
154
250
  context "" do
155
251
  setup do
156
- AWS::S3::Base.stubs(:establish_connection!)
157
252
  rebuild_model :storage => :s3,
158
253
  :s3_credentials => {
159
254
  :production => { :bucket => "prod_bucket" },
@@ -173,7 +268,6 @@ class S3Test < Test::Unit::TestCase
173
268
 
174
269
  context "generating a url with a proc as the host alias" do
175
270
  setup do
176
- AWS::S3::Base.stubs(:establish_connection!)
177
271
  rebuild_model :storage => :s3,
178
272
  :s3_credentials => { :bucket => "prod_bucket" },
179
273
  :s3_host_alias => Proc.new{|atch| "cdn#{atch.instance.counter % 4}.example.com"},
@@ -203,7 +297,6 @@ class S3Test < Test::Unit::TestCase
203
297
 
204
298
  context "" do
205
299
  setup do
206
- AWS::S3::Base.stubs(:establish_connection!)
207
300
  rebuild_model :storage => :s3,
208
301
  :s3_credentials => {},
209
302
  :bucket => "bucket",
@@ -220,7 +313,6 @@ class S3Test < Test::Unit::TestCase
220
313
 
221
314
  context "Generating a secure url with an expiration" do
222
315
  setup do
223
- AWS::S3::Base.stubs(:establish_connection!)
224
316
  rebuild_model :storage => :s3,
225
317
  :s3_credentials => {
226
318
  :production => { :bucket => "prod_bucket" },
@@ -236,7 +328,9 @@ class S3Test < Test::Unit::TestCase
236
328
  @dummy = Dummy.new
237
329
  @dummy.avatar = StringIO.new(".")
238
330
 
239
- AWS::S3::S3Object.expects(:url_for).with("avatars/stringio.txt", "prod_bucket", { :expires_in => 3600, :use_ssl => true })
331
+ object = stub
332
+ @dummy.avatar.stubs(:s3_object).returns(object)
333
+ object.expects(:url_for).with(:read, :expires => 3600, :secure => true)
240
334
 
241
335
  @dummy.avatar.expiring_url
242
336
  end
@@ -246,9 +340,8 @@ class S3Test < Test::Unit::TestCase
246
340
  end
247
341
  end
248
342
 
249
- context "Generating a url with an expiration" do
343
+ context "Generating a url with an expiration for each style" do
250
344
  setup do
251
- AWS::S3::Base.stubs(:establish_connection!)
252
345
  rebuild_model :storage => :s3,
253
346
  :s3_credentials => {
254
347
  :production => { :bucket => "prod_bucket" },
@@ -263,22 +356,25 @@ class S3Test < Test::Unit::TestCase
263
356
 
264
357
  @dummy = Dummy.new
265
358
  @dummy.avatar = StringIO.new(".")
359
+ end
266
360
 
267
- AWS::S3::S3Object.expects(:url_for).with("avatars/original/stringio.txt", "prod_bucket", { :expires_in => 3600, :use_ssl => true })
268
- @dummy.avatar.expiring_url
269
-
270
- AWS::S3::S3Object.expects(:url_for).with("avatars/thumb/stringio.txt", "prod_bucket", { :expires_in => 1800, :use_ssl => true })
361
+ should "should generate a url for the thumb" do
362
+ object = stub
363
+ @dummy.avatar.stubs(:s3_object).with(:thumb).returns(object)
364
+ object.expects(:url_for).with(:read, :expires => 1800, :secure => true)
271
365
  @dummy.avatar.expiring_url(1800, :thumb)
272
366
  end
273
367
 
274
- should "should succeed" do
275
- assert true
368
+ should "should generate a url for the default style" do
369
+ object = stub
370
+ @dummy.avatar.stubs(:s3_object).with(:original).returns(object)
371
+ object.expects(:url_for).with(:read, :expires => 1800, :secure => true)
372
+ @dummy.avatar.expiring_url(1800)
276
373
  end
277
374
  end
278
375
 
279
376
  context "Parsing S3 credentials with a bucket in them" do
280
377
  setup do
281
- AWS::S3::Base.stubs(:establish_connection!)
282
378
  rebuild_model :storage => :s3,
283
379
  :s3_credentials => {
284
380
  :production => { :bucket => "prod_bucket" },
@@ -290,18 +386,20 @@ class S3Test < Test::Unit::TestCase
290
386
  should "get the right bucket in production" do
291
387
  rails_env("production")
292
388
  assert_equal "prod_bucket", @dummy.avatar.bucket_name
389
+ assert_equal "prod_bucket", @dummy.avatar.s3_bucket.name
293
390
  end
294
391
 
295
392
  should "get the right bucket in development" do
296
393
  rails_env("development")
297
394
  assert_equal "dev_bucket", @dummy.avatar.bucket_name
395
+ assert_equal "dev_bucket", @dummy.avatar.s3_bucket.name
298
396
  end
299
397
  end
300
398
 
301
399
  context "Parsing S3 credentials with a s3_host_name in them" do
302
400
  setup do
303
- AWS::S3::Base.stubs(:establish_connection!)
304
401
  rebuild_model :storage => :s3,
402
+ :bucket => 'testing',
305
403
  :s3_credentials => {
306
404
  :production => { :s3_host_name => "s3-world-end.amazonaws.com" },
307
405
  :development => { :s3_host_name => "s3-ap-northeast-1.amazonaws.com" }
@@ -312,16 +410,19 @@ class S3Test < Test::Unit::TestCase
312
410
  should "get the right s3_host_name in production" do
313
411
  rails_env("production")
314
412
  assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_host_name
413
+ assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
315
414
  end
316
415
 
317
416
  should "get the right s3_host_name in development" do
318
417
  rails_env("development")
319
418
  assert_match %r{^s3-ap-northeast-1.amazonaws.com}, @dummy.avatar.s3_host_name
419
+ assert_match %r{^s3-ap-northeast-1.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
320
420
  end
321
421
 
322
422
  should "get the right s3_host_name if the key does not exist" do
323
423
  rails_env("test")
324
424
  assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_host_name
425
+ assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
325
426
  end
326
427
  end
327
428
 
@@ -346,7 +447,7 @@ class S3Test < Test::Unit::TestCase
346
447
 
347
448
  context "when assigned" do
348
449
  setup do
349
- @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
450
+ @file = File.new(fixture_file('5k.png'), 'rb')
350
451
  @dummy = Dummy.new
351
452
  @dummy.avatar = @file
352
453
  end
@@ -361,7 +462,11 @@ class S3Test < Test::Unit::TestCase
361
462
 
362
463
  context "and saved" do
363
464
  setup do
364
- AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path, anything, 'testing', :content_type => 'image/png', :access => :public_read)
465
+ object = stub
466
+ @dummy.avatar.stubs(:s3_object).returns(object)
467
+ object.expects(:write).with(anything,
468
+ :content_type => "image/png",
469
+ :acl => :public_read)
365
470
  @dummy.save
366
471
  end
367
472
 
@@ -371,7 +476,6 @@ class S3Test < Test::Unit::TestCase
371
476
  end
372
477
 
373
478
  should "delete tempfiles" do
374
- AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path, anything, 'testing', :content_type => 'image/png', :access => :public_read)
375
479
  File.stubs(:exist?).returns(true)
376
480
  Paperclip::Tempfile.any_instance.expects(:close).at_least_once()
377
481
  Paperclip::Tempfile.any_instance.expects(:unlink).at_least_once()
@@ -381,11 +485,12 @@ class S3Test < Test::Unit::TestCase
381
485
 
382
486
  context "and saved without a bucket" do
383
487
  setup do
384
- class AWS::S3::NoSuchBucket < AWS::S3::ResponseError
385
- # Force the class to be created as a proper subclass of ResponseError thanks to AWS::S3's autocreation of exceptions
386
- end
387
- AWS::S3::Bucket.expects(:create).with("testing")
388
- AWS::S3::S3Object.stubs(:store).raises(AWS::S3::NoSuchBucket.new(:message, :response)).then.returns(true)
488
+ AWS::S3::BucketCollection.any_instance.expects(:create).with("testing")
489
+ AWS::S3::S3Object.any_instance.stubs(:write).
490
+ raises(AWS::S3::Errors::NoSuchBucket.new(stub,
491
+ stub(:status => 404,
492
+ :body => "<foo/>"))).
493
+ then.returns(nil)
389
494
  @dummy.save
390
495
  end
391
496
 
@@ -396,8 +501,8 @@ class S3Test < Test::Unit::TestCase
396
501
 
397
502
  context "and remove" do
398
503
  setup do
399
- AWS::S3::S3Object.stubs(:exists?).returns(true)
400
- AWS::S3::S3Object.stubs(:delete)
504
+ AWS::S3::S3Object.any_instance.stubs(:exists?).returns(true)
505
+ AWS::S3::S3Object.any_instance.stubs(:delete)
401
506
  @dummy.destroy_attached_files
402
507
  end
403
508
 
@@ -410,7 +515,6 @@ class S3Test < Test::Unit::TestCase
410
515
 
411
516
  context "An attachment with S3 storage and bucket defined as a Proc" do
412
517
  setup do
413
- AWS::S3::Base.stubs(:establish_connection!)
414
518
  rebuild_model :storage => :s3,
415
519
  :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
416
520
  :s3_credentials => {:not => :important}
@@ -418,13 +522,14 @@ class S3Test < Test::Unit::TestCase
418
522
 
419
523
  should "get the right bucket name" do
420
524
  assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
525
+ assert "bucket_a", Dummy.new(:other => 'a').avatar.s3_bucket.name
421
526
  assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
527
+ assert "bucket_b", Dummy.new(:other => 'b').avatar.s3_bucket.name
422
528
  end
423
529
  end
424
530
 
425
531
  context "An attachment with S3 storage and specific s3 headers set" do
426
532
  setup do
427
- AWS::S3::Base.stubs(:establish_connection!)
428
533
  rebuild_model :storage => :s3,
429
534
  :bucket => "testing",
430
535
  :path => ":attachment/:style/:basename.:extension",
@@ -435,6 +540,45 @@ class S3Test < Test::Unit::TestCase
435
540
  :s3_headers => {'Cache-Control' => 'max-age=31557600'}
436
541
  end
437
542
 
543
+ context "when assigned" do
544
+ setup do
545
+ @file = File.new(fixture_file('5k.png'), 'rb')
546
+ @dummy = Dummy.new
547
+ @dummy.avatar = @file
548
+ end
549
+
550
+ teardown { @file.close }
551
+
552
+ context "and saved" do
553
+ setup do
554
+ object = stub
555
+ @dummy.avatar.stubs(:s3_object).returns(object)
556
+ object.expects(:write).with(anything,
557
+ :content_type => "image/png",
558
+ :acl => :public_read,
559
+ :cache_control => 'max-age=31557600')
560
+ @dummy.save
561
+ end
562
+
563
+ should "succeed" do
564
+ assert true
565
+ end
566
+ end
567
+ end
568
+ end
569
+
570
+ context "An attachment with S3 storage and metadata set using header names" do
571
+ setup do
572
+ rebuild_model :storage => :s3,
573
+ :bucket => "testing",
574
+ :path => ":attachment/:style/:basename.:extension",
575
+ :s3_credentials => {
576
+ 'access_key_id' => "12345",
577
+ 'secret_access_key' => "54321"
578
+ },
579
+ :s3_headers => {'x-amz-meta-color' => 'red'}
580
+ end
581
+
438
582
  context "when assigned" do
439
583
  setup do
440
584
  @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
@@ -446,13 +590,129 @@ class S3Test < Test::Unit::TestCase
446
590
 
447
591
  context "and saved" do
448
592
  setup do
449
- AWS::S3::Base.stubs(:establish_connection!)
450
- AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path,
451
- anything,
452
- 'testing',
453
- :content_type => 'image/png',
454
- :access => :public_read,
455
- 'Cache-Control' => 'max-age=31557600')
593
+ object = stub
594
+ @dummy.avatar.stubs(:s3_object).returns(object)
595
+ object.expects(:write).with(anything,
596
+ :content_type => "image/png",
597
+ :acl => :public_read,
598
+ :metadata => { "color" => "red" })
599
+ @dummy.save
600
+ end
601
+
602
+ should "succeed" do
603
+ assert true
604
+ end
605
+ end
606
+ end
607
+ end
608
+
609
+ context "An attachment with S3 storage and metadata set using the :s3_metadata option" do
610
+ setup do
611
+ rebuild_model :storage => :s3,
612
+ :bucket => "testing",
613
+ :path => ":attachment/:style/:basename.:extension",
614
+ :s3_credentials => {
615
+ 'access_key_id' => "12345",
616
+ 'secret_access_key' => "54321"
617
+ },
618
+ :s3_metadata => { "color" => "red" }
619
+ end
620
+
621
+ context "when assigned" do
622
+ setup do
623
+ @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
624
+ @dummy = Dummy.new
625
+ @dummy.avatar = @file
626
+ end
627
+
628
+ teardown { @file.close }
629
+
630
+ context "and saved" do
631
+ setup do
632
+ object = stub
633
+ @dummy.avatar.stubs(:s3_object).returns(object)
634
+ object.expects(:write).with(anything,
635
+ :content_type => "image/png",
636
+ :acl => :public_read,
637
+ :metadata => { "color" => "red" })
638
+ @dummy.save
639
+ end
640
+
641
+ should "succeed" do
642
+ assert true
643
+ end
644
+ end
645
+ end
646
+ end
647
+
648
+ context "An attachment with S3 storage and storage class set using the header name" do
649
+ setup do
650
+ rebuild_model :storage => :s3,
651
+ :bucket => "testing",
652
+ :path => ":attachment/:style/:basename.:extension",
653
+ :s3_credentials => {
654
+ 'access_key_id' => "12345",
655
+ 'secret_access_key' => "54321"
656
+ },
657
+ :s3_headers => { "x-amz-storage-class" => "reduced_redundancy" }
658
+ end
659
+
660
+ context "when assigned" do
661
+ setup do
662
+ @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
663
+ @dummy = Dummy.new
664
+ @dummy.avatar = @file
665
+ end
666
+
667
+ teardown { @file.close }
668
+
669
+ context "and saved" do
670
+ setup do
671
+ object = stub
672
+ @dummy.avatar.stubs(:s3_object).returns(object)
673
+ object.expects(:write).with(anything,
674
+ :content_type => "image/png",
675
+ :acl => :public_read,
676
+ :storage_class => "reduced_redundancy")
677
+ @dummy.save
678
+ end
679
+
680
+ should "succeed" do
681
+ assert true
682
+ end
683
+ end
684
+ end
685
+ end
686
+
687
+ context "An attachment with S3 storage and storage class set using the :storage_class option" do
688
+ setup do
689
+ rebuild_model :storage => :s3,
690
+ :bucket => "testing",
691
+ :path => ":attachment/:style/:basename.:extension",
692
+ :s3_credentials => {
693
+ 'access_key_id' => "12345",
694
+ 'secret_access_key' => "54321"
695
+ },
696
+ :s3_storage_class => :reduced_redundancy
697
+ end
698
+
699
+ context "when assigned" do
700
+ setup do
701
+ @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
702
+ @dummy = Dummy.new
703
+ @dummy.avatar = @file
704
+ end
705
+
706
+ teardown { @file.close }
707
+
708
+ context "and saved" do
709
+ setup do
710
+ object = stub
711
+ @dummy.avatar.stubs(:s3_object).returns(object)
712
+ object.expects(:write).with(anything,
713
+ :content_type => "image/png",
714
+ :acl => :public_read,
715
+ :storage_class => :reduced_redundancy)
456
716
  @dummy.save
457
717
  end
458
718
 
@@ -464,25 +724,25 @@ class S3Test < Test::Unit::TestCase
464
724
  end
465
725
 
466
726
  context "with S3 credentials supplied as Pathname" do
467
- setup do
468
- ENV['S3_KEY'] = 'pathname_key'
469
- ENV['S3_BUCKET'] = 'pathname_bucket'
470
- ENV['S3_SECRET'] = 'pathname_secret'
727
+ setup do
728
+ ENV['S3_KEY'] = 'pathname_key'
729
+ ENV['S3_BUCKET'] = 'pathname_bucket'
730
+ ENV['S3_SECRET'] = 'pathname_secret'
471
731
 
472
- rails_env('test')
732
+ rails_env('test')
473
733
 
474
- rebuild_model :storage => :s3,
475
- :s3_credentials => Pathname.new(File.join(File.dirname(__FILE__))).join("../fixtures/s3.yml")
734
+ rebuild_model :storage => :s3,
735
+ :s3_credentials => Pathname.new(fixture_file('s3.yml'))
476
736
 
477
- Dummy.delete_all
478
- @dummy = Dummy.new
479
- end
737
+ Dummy.delete_all
738
+ @dummy = Dummy.new
739
+ end
480
740
 
481
- should "parse the credentials" do
482
- assert_equal 'pathname_bucket', @dummy.avatar.bucket_name
483
- assert_equal 'pathname_key', AWS::S3::Base.connection.options[:access_key_id]
484
- assert_equal 'pathname_secret', AWS::S3::Base.connection.options[:secret_access_key]
485
- end
741
+ should "parse the credentials" do
742
+ assert_equal 'pathname_bucket', @dummy.avatar.bucket_name
743
+ assert_equal 'pathname_key', @dummy.avatar.s3_bucket.config.access_key_id
744
+ assert_equal 'pathname_secret', @dummy.avatar.s3_bucket.config.secret_access_key
745
+ end
486
746
  end
487
747
 
488
748
  context "with S3 credentials in a YAML file" do
@@ -494,7 +754,7 @@ class S3Test < Test::Unit::TestCase
494
754
  rails_env('test')
495
755
 
496
756
  rebuild_model :storage => :s3,
497
- :s3_credentials => File.new(File.join(File.dirname(__FILE__), "../fixtures/s3.yml"))
757
+ :s3_credentials => File.new(fixture_file('s3.yml'))
498
758
 
499
759
  Dummy.delete_all
500
760
 
@@ -503,8 +763,8 @@ class S3Test < Test::Unit::TestCase
503
763
 
504
764
  should "run the file through ERB" do
505
765
  assert_equal 'env_bucket', @dummy.avatar.bucket_name
506
- assert_equal 'env_key', AWS::S3::Base.connection.options[:access_key_id]
507
- assert_equal 'env_secret', AWS::S3::Base.connection.options[:secret_access_key]
766
+ assert_equal 'env_key', @dummy.avatar.s3_bucket.config.access_key_id
767
+ assert_equal 'env_secret', @dummy.avatar.s3_bucket.config.secret_access_key
508
768
  end
509
769
  end
510
770
 
@@ -522,7 +782,7 @@ class S3Test < Test::Unit::TestCase
522
782
 
523
783
  context "when assigned" do
524
784
  setup do
525
- @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
785
+ @file = File.new(fixture_file('5k.png'), 'rb')
526
786
  @dummy = Dummy.new
527
787
  @dummy.avatar = @file
528
788
  end
@@ -531,12 +791,11 @@ class S3Test < Test::Unit::TestCase
531
791
 
532
792
  context "and saved" do
533
793
  setup do
534
- AWS::S3::Base.stubs(:establish_connection!)
535
- AWS::S3::S3Object.expects(:store).with(@dummy.avatar.path,
536
- anything,
537
- 'testing',
538
- :content_type => 'image/png',
539
- :access => :public_read)
794
+ object = stub
795
+ @dummy.avatar.stubs(:s3_object).returns(object)
796
+ object.expects(:write).with(anything,
797
+ :content_type => "image/png",
798
+ :acl => :public_read)
540
799
  @dummy.save
541
800
  end
542
801
 
@@ -561,7 +820,7 @@ class S3Test < Test::Unit::TestCase
561
820
 
562
821
  context "when assigned" do
563
822
  setup do
564
- @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
823
+ @file = File.new(fixture_file('5k.png'), 'rb')
565
824
  @dummy = Dummy.new
566
825
  @dummy.avatar = @file
567
826
  end
@@ -570,12 +829,11 @@ class S3Test < Test::Unit::TestCase
570
829
 
571
830
  context "and saved" do
572
831
  setup do
573
- AWS::S3::Base.stubs(:establish_connection!)
574
- AWS::S3::S3Object.expects(:store).with(@dummy.avatar.path,
575
- anything,
576
- 'testing',
577
- :content_type => 'image/png',
578
- :access => :private)
832
+ object = stub
833
+ @dummy.avatar.stubs(:s3_object).returns(object)
834
+ object.expects(:write).with(anything,
835
+ :content_type => "image/png",
836
+ :acl => :private)
579
837
  @dummy.save
580
838
  end
581
839
 
@@ -606,7 +864,7 @@ class S3Test < Test::Unit::TestCase
606
864
 
607
865
  context "when assigned" do
608
866
  setup do
609
- @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
867
+ @file = File.new(fixture_file('5k.png'), 'rb')
610
868
  @dummy = Dummy.new
611
869
  @dummy.avatar = @file
612
870
  end
@@ -615,13 +873,12 @@ class S3Test < Test::Unit::TestCase
615
873
 
616
874
  context "and saved" do
617
875
  setup do
618
- AWS::S3::Base.stubs(:establish_connection!)
619
876
  [:thumb, :original].each do |style|
620
- AWS::S3::S3Object.expects(:store).with("avatars/#{style}/5k.png",
621
- anything,
622
- 'testing',
623
- :content_type => 'image/png',
624
- :access => style == :thumb ? :public_read : :private)
877
+ object = stub
878
+ @dummy.avatar.stubs(:s3_object).with(style).returns(object)
879
+ object.expects(:write).with(anything,
880
+ :content_type => "image/png",
881
+ :acl => style == :thumb ? :public_read : :private)
625
882
  end
626
883
  @dummy.save
627
884
  end
@@ -654,7 +911,7 @@ class S3Test < Test::Unit::TestCase
654
911
 
655
912
  context "when assigned" do
656
913
  setup do
657
- @file = File.new(File.join(File.dirname(__FILE__), '..', 'fixtures', '5k.png'), 'rb')
914
+ @file = File.new(fixture_file('5k.png'), 'rb')
658
915
  @dummy = Dummy.new
659
916
  @dummy.stubs(:private_attachment? => true)
660
917
  @dummy.avatar = @file
@@ -664,15 +921,12 @@ class S3Test < Test::Unit::TestCase
664
921
 
665
922
  context "and saved" do
666
923
  setup do
667
- AWS::S3::Base.stubs(:establish_connection!)
668
924
  [:thumb, :original].each do |style|
669
- AWS::S3::S3Object.expects(:store).with(
670
- "avatars/#{style}/5k.png",
671
- anything,
672
- 'testing',
673
- :content_type => 'image/png',
674
- :access => style == :thumb ? :public_read : :private
675
- )
925
+ object = stub
926
+ @dummy.avatar.stubs(:s3_object).with(style).returns(object)
927
+ object.expects(:write).with(anything,
928
+ :content_type => "image/png",
929
+ :acl => style == :thumb ? :public_read : :private)
676
930
  end
677
931
  @dummy.save
678
932
  end
@@ -686,4 +940,53 @@ class S3Test < Test::Unit::TestCase
686
940
 
687
941
  end
688
942
  end
943
+
944
+ context "An attachment with S3 storage and metadata set using a proc as headers" do
945
+ setup do
946
+ rebuild_model(
947
+ :storage => :s3,
948
+ :bucket => "testing",
949
+ :path => ":attachment/:style/:basename.:extension",
950
+ :styles => {
951
+ :thumb => "80x80>"
952
+ },
953
+ :s3_credentials => {
954
+ 'access_key_id' => "12345",
955
+ 'secret_access_key' => "54321"
956
+ },
957
+ :s3_headers => lambda {|attachment|
958
+ {'Content-Disposition' => "attachment; filename=\"#{attachment.name}\""}
959
+ }
960
+ )
961
+ end
962
+
963
+ context "when assigned" do
964
+ setup do
965
+ @file = File.new(fixture_file('5k.png'), 'rb')
966
+ @dummy = Dummy.new
967
+ @dummy.stubs(:name => 'Custom Avatar Name.png')
968
+ @dummy.avatar = @file
969
+ end
970
+
971
+ teardown { @file.close }
972
+
973
+ context "and saved" do
974
+ setup do
975
+ [:thumb, :original].each do |style|
976
+ object = stub
977
+ @dummy.avatar.stubs(:s3_object).with(style).returns(object)
978
+ object.expects(:write).with(anything,
979
+ :content_type => "image/png",
980
+ :acl => :public_read,
981
+ :content_disposition => 'attachment; filename="Custom Avatar Name.png"')
982
+ end
983
+ @dummy.save
984
+ end
985
+
986
+ should "succeed" do
987
+ assert true
988
+ end
989
+ end
990
+ end
991
+ end
689
992
  end