paperclip 4.2.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +1066 -0
  3. data/.rubocop.yml +1 -0
  4. data/.travis.yml +18 -15
  5. data/Appraisals +20 -12
  6. data/CONTRIBUTING.md +19 -8
  7. data/Gemfile +4 -9
  8. data/LICENSE +1 -1
  9. data/NEWS +101 -31
  10. data/README.md +243 -159
  11. data/RELEASING.md +17 -0
  12. data/Rakefile +1 -1
  13. data/UPGRADING +12 -9
  14. data/features/basic_integration.feature +8 -4
  15. data/features/migration.feature +0 -24
  16. data/features/step_definitions/attachment_steps.rb +27 -21
  17. data/features/step_definitions/html_steps.rb +2 -2
  18. data/features/step_definitions/rails_steps.rb +11 -17
  19. data/features/step_definitions/s3_steps.rb +2 -2
  20. data/features/step_definitions/web_steps.rb +1 -103
  21. data/features/support/file_helpers.rb +2 -2
  22. data/gemfiles/4.2.awsv2.0.gemfile +17 -0
  23. data/gemfiles/4.2.awsv2.1.gemfile +17 -0
  24. data/gemfiles/{4.1.gemfile → 4.2.awsv2.gemfile} +4 -3
  25. data/gemfiles/5.0.awsv2.0.gemfile +17 -0
  26. data/gemfiles/5.0.awsv2.1.gemfile +17 -0
  27. data/gemfiles/{4.2.gemfile → 5.0.awsv2.gemfile} +4 -3
  28. data/lib/paperclip/attachment.rb +19 -16
  29. data/lib/paperclip/attachment_registry.rb +3 -2
  30. data/lib/paperclip/callbacks.rb +8 -6
  31. data/lib/paperclip/content_type_detector.rb +27 -11
  32. data/lib/paperclip/errors.rb +3 -1
  33. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  34. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  35. data/lib/paperclip/glue.rb +1 -1
  36. data/lib/paperclip/has_attached_file.rb +9 -2
  37. data/lib/paperclip/helpers.rb +14 -10
  38. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  39. data/lib/paperclip/interpolations.rb +18 -13
  40. data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -0
  41. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
  42. data/lib/paperclip/io_adapters/uri_adapter.rb +3 -1
  43. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  44. data/lib/paperclip/media_type_spoof_detector.rb +2 -2
  45. data/lib/paperclip/rails_environment.rb +25 -0
  46. data/lib/paperclip/schema.rb +3 -9
  47. data/lib/paperclip/storage/fog.rb +21 -12
  48. data/lib/paperclip/storage/s3.rb +51 -50
  49. data/lib/paperclip/thumbnail.rb +2 -3
  50. data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
  51. data/lib/paperclip/version.rb +3 -1
  52. data/lib/paperclip.rb +15 -4
  53. data/lib/tasks/paperclip.rake +17 -1
  54. data/paperclip.gemspec +18 -15
  55. data/spec/paperclip/attachment_definitions_spec.rb +1 -1
  56. data/spec/paperclip/attachment_processing_spec.rb +2 -4
  57. data/spec/paperclip/attachment_registry_spec.rb +84 -13
  58. data/spec/paperclip/attachment_spec.rb +91 -31
  59. data/spec/paperclip/content_type_detector_spec.rb +8 -1
  60. data/spec/paperclip/file_command_content_type_detector_spec.rb +0 -1
  61. data/spec/paperclip/geometry_spec.rb +1 -1
  62. data/spec/paperclip/glue_spec.rb +44 -0
  63. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  64. data/spec/paperclip/integration_spec.rb +4 -3
  65. data/spec/paperclip/interpolations_spec.rb +16 -13
  66. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +2 -1
  67. data/spec/paperclip/io_adapters/file_adapter_spec.rb +4 -1
  68. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +12 -0
  69. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +4 -0
  70. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +27 -0
  71. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
  72. data/spec/paperclip/media_type_spoof_detector_spec.rb +34 -11
  73. data/spec/paperclip/paperclip_spec.rb +4 -29
  74. data/spec/paperclip/plural_cache_spec.rb +17 -16
  75. data/spec/paperclip/rails_environment_spec.rb +33 -0
  76. data/spec/paperclip/storage/fog_spec.rb +42 -3
  77. data/spec/paperclip/storage/s3_live_spec.rb +8 -4
  78. data/spec/paperclip/storage/s3_spec.rb +255 -180
  79. data/spec/paperclip/tempfile_factory_spec.rb +4 -0
  80. data/spec/paperclip/thumbnail_spec.rb +16 -0
  81. data/spec/paperclip/url_generator_spec.rb +1 -1
  82. data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
  83. data/spec/paperclip/validators_spec.rb +3 -3
  84. data/spec/spec_helper.rb +6 -1
  85. data/spec/support/assertions.rb +7 -0
  86. data/spec/support/fake_model.rb +4 -0
  87. data/spec/support/fixtures/empty.xlsx +0 -0
  88. data/spec/support/matchers/have_column.rb +11 -2
  89. data/spec/support/model_reconstruction.rb +9 -1
  90. data/spec/support/reporting.rb +11 -0
  91. metadata +105 -54
  92. data/RUNNING_TESTS.md +0 -4
  93. data/cucumber/paperclip_steps.rb +0 -6
  94. data/gemfiles/3.2.gemfile +0 -19
  95. data/gemfiles/4.0.gemfile +0 -19
  96. data/lib/paperclip/locales/de.yml +0 -18
  97. data/lib/paperclip/locales/es.yml +0 -18
  98. data/lib/paperclip/locales/ja.yml +0 -18
  99. data/lib/paperclip/locales/pt-BR.yml +0 -18
  100. data/lib/paperclip/locales/zh-CN.yml +0 -18
  101. data/lib/paperclip/locales/zh-HK.yml +0 -18
  102. data/lib/paperclip/locales/zh-TW.yml +0 -18
  103. data/spec/support/mock_model.rb +0 -2
  104. data/spec/support/rails_helpers.rb +0 -7
@@ -73,10 +73,13 @@ describe Paperclip::FileAdapter do
73
73
  end
74
74
  end
75
75
 
76
- context "file with content type derived from file command on *nix" do
76
+ context "file with content type derived from file contents on *nix" do
77
77
  before do
78
78
  MIME::Types.stubs(:type_for).returns([])
79
79
  Paperclip.stubs(:run).returns("application/vnd.ms-office\n")
80
+ Paperclip::ContentTypeDetector.any_instance
81
+ .stubs(:type_from_mime_magic).returns("application/vnd.ms-office")
82
+
80
83
  @subject = Paperclip.io_adapters.for(@file)
81
84
  end
82
85
 
@@ -98,4 +98,16 @@ describe Paperclip::HttpUrlProxyAdapter do
98
98
  end
99
99
  end
100
100
 
101
+ context "a url with special characters in the filename" do
102
+ it "returns a encoded filename" do
103
+ Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).
104
+ returns(StringIO.new("x"))
105
+ url = "https://github.com/thoughtbot/paperclip-öäü字´½♥زÈ.png"
106
+ subject = Paperclip.io_adapters.for(url)
107
+ filename = "paperclip-%C3%B6%C3%A4%C3%BC%E5%AD%97%C2%B4%C2%BD%E2%99%A5"\
108
+ "%C3%98%C2%B2%C3%88.png"
109
+
110
+ assert_equal filename, subject.original_filename
111
+ end
112
+ end
101
113
  end
@@ -20,6 +20,10 @@ describe Paperclip::StringioAdapter do
20
20
  assert_equal 6, @subject.size
21
21
  end
22
22
 
23
+ it "returns the length of the data" do
24
+ assert_equal 6, @subject.length
25
+ end
26
+
23
27
  it "generates an MD5 hash of the contents" do
24
28
  assert_equal Digest::MD5.hexdigest(@contents), @subject.fingerprint
25
29
  end
@@ -99,4 +99,31 @@ describe Paperclip::UriAdapter do
99
99
  end
100
100
  end
101
101
 
102
+ describe "#download_content" do
103
+ before do
104
+ Paperclip::UriAdapter.any_instance.stubs(:open).returns(StringIO.new("xxx"))
105
+ @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
106
+ @subject = Paperclip.io_adapters.for(@uri)
107
+ end
108
+
109
+ after do
110
+ @subject.send(:download_content)
111
+ end
112
+
113
+ context "with default read_timeout" do
114
+ it "calls open without options" do
115
+ @subject.expects(:open).with(@uri, {}).at_least_once
116
+ end
117
+ end
118
+
119
+ context "with custom read_timeout" do
120
+ before do
121
+ Paperclip.options[:read_timeout] = 120
122
+ end
123
+
124
+ it "calls open with read_timeout option" do
125
+ @subject.expects(:open).with(@uri, read_timeout: 120).at_least_once
126
+ end
127
+ end
128
+ end
102
129
  end
@@ -17,22 +17,26 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
17
17
 
18
18
  it "rejects a class with no validation" do
19
19
  expect(matcher).to_not accept(Dummy)
20
+ expect { matcher.failure_message }.to_not raise_error
20
21
  end
21
22
 
22
23
  it 'rejects a class when the validation fails' do
23
24
  Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
24
25
  expect(matcher).to_not accept(Dummy)
26
+ expect { matcher.failure_message }.to_not raise_error
25
27
  end
26
28
 
27
29
  it "accepts a class with a matching validation" do
28
30
  Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
29
31
  expect(matcher).to accept(Dummy)
32
+ expect { matcher.failure_message }.to_not raise_error
30
33
  end
31
34
 
32
35
  it "accepts a class with other validations but matching types" do
33
36
  Dummy.validates_presence_of :title
34
37
  Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
35
38
  expect(matcher).to accept(Dummy)
39
+ expect { matcher.failure_message }.to_not raise_error
36
40
  end
37
41
 
38
42
  it "accepts a class that matches and a matcher that only specifies 'allowing'" do
@@ -40,6 +44,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
40
44
  matcher = plain_matcher.allowing(%w(image/png image/jpeg))
41
45
 
42
46
  expect(matcher).to accept(Dummy)
47
+ expect { matcher.failure_message }.to_not raise_error
43
48
  end
44
49
 
45
50
  it "rejects a class that does not match and a matcher that only specifies 'allowing'" do
@@ -47,6 +52,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
47
52
  matcher = plain_matcher.allowing(%w(image/png image/jpeg))
48
53
 
49
54
  expect(matcher).to_not accept(Dummy)
55
+ expect { matcher.failure_message }.to_not raise_error
50
56
  end
51
57
 
52
58
  it "accepts a class that matches and a matcher that only specifies 'rejecting'" do
@@ -54,6 +60,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
54
60
  matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
55
61
 
56
62
  expect(matcher).to accept(Dummy)
63
+ expect { matcher.failure_message }.to_not raise_error
57
64
  end
58
65
 
59
66
  it "rejects a class that does not match and a matcher that only specifies 'rejecting'" do
@@ -61,6 +68,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
61
68
  matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
62
69
 
63
70
  expect(matcher).to_not accept(Dummy)
71
+ expect { matcher.failure_message }.to_not raise_error
64
72
  end
65
73
 
66
74
  context "using an :if to control the validation" do
@@ -75,12 +83,14 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
75
83
  dummy = Dummy.new
76
84
  dummy.go = true
77
85
  expect(matcher).to accept(dummy)
86
+ expect { matcher.failure_message }.to_not raise_error
78
87
  end
79
88
 
80
89
  it "does not run the validation if the control is false" do
81
90
  dummy = Dummy.new
82
91
  dummy.go = false
83
92
  expect(matcher).to_not accept(dummy)
93
+ expect { matcher.failure_message }.to_not raise_error
84
94
  end
85
95
  end
86
96
 
@@ -3,32 +3,32 @@ require 'spec_helper'
3
3
  describe Paperclip::MediaTypeSpoofDetector do
4
4
  it 'rejects a file that is named .html and identifies as PNG' do
5
5
  file = File.open(fixture_file("5k.png"))
6
- assert Paperclip::MediaTypeSpoofDetector.using(file, "5k.html").spoofed?
6
+ assert Paperclip::MediaTypeSpoofDetector.using(file, "5k.html", "image/png").spoofed?
7
7
  end
8
8
 
9
9
  it 'does not reject a file that is named .jpg and identifies as PNG' do
10
10
  file = File.open(fixture_file("5k.png"))
11
- assert ! Paperclip::MediaTypeSpoofDetector.using(file, "5k.jpg").spoofed?
11
+ assert ! Paperclip::MediaTypeSpoofDetector.using(file, "5k.jpg", "image/png").spoofed?
12
12
  end
13
13
 
14
14
  it 'does not reject a file that is named .html and identifies as HTML' do
15
15
  file = File.open(fixture_file("empty.html"))
16
- assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html").spoofed?
16
+ assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "text/html").spoofed?
17
17
  end
18
18
 
19
19
  it 'does not reject a file that does not have a name' do
20
20
  file = File.open(fixture_file("empty.html"))
21
- assert ! Paperclip::MediaTypeSpoofDetector.using(file, "").spoofed?
21
+ assert ! Paperclip::MediaTypeSpoofDetector.using(file, "", "text/html").spoofed?
22
22
  end
23
23
 
24
24
  it 'does not reject a file that does have an extension' do
25
25
  file = File.open(fixture_file("empty.html"))
26
- assert ! Paperclip::MediaTypeSpoofDetector.using(file, "data").spoofed?
26
+ assert ! Paperclip::MediaTypeSpoofDetector.using(file, "data", "text/html").spoofed?
27
27
  end
28
28
 
29
29
  it 'does not reject when the supplied file is an IOAdapter' do
30
30
  adapter = Paperclip.io_adapters.for(File.new(fixture_file("5k.png")))
31
- assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename).spoofed?
31
+ assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename, adapter.content_type).spoofed?
32
32
  end
33
33
 
34
34
  it 'does not reject when the extension => content_type is in :content_type_mappings' do
@@ -38,19 +38,42 @@ describe Paperclip::MediaTypeSpoofDetector do
38
38
  file.puts "Certificate!"
39
39
  file.close
40
40
  adapter = Paperclip.io_adapters.for(File.new(file.path));
41
- assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename).spoofed?
41
+ assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename, adapter.content_type).spoofed?
42
42
  ensure
43
43
  Paperclip.options[:content_type_mappings] = {}
44
44
  end
45
45
  end
46
46
 
47
- it "rejects a file if named .html and is as HTML, but we're told JPG" do
48
- file = File.open(fixture_file("empty.html"))
49
- assert Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "image/jpg").spoofed?
47
+ context "file named .html and is as HTML, but we're told JPG" do
48
+ let(:file) { File.open(fixture_file("empty.html")) }
49
+ let(:spoofed?) { Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "image/jpg").spoofed? }
50
+
51
+ it "rejects the file" do
52
+ assert spoofed?
53
+ end
54
+
55
+ it "logs info about the detected spoof" do
56
+ Paperclip.expects(:log).with('Content Type Spoof: Filename empty.html (image/jpg from Headers, ["text/html"] from Extension), content type discovered from file command: text/html. See documentation to allow this combination.')
57
+ spoofed?
58
+ end
50
59
  end
51
60
 
52
- it "does not reject is content_type is empty but otherwise checks out" do
61
+ it "does not reject if content_type is empty but otherwise checks out" do
53
62
  file = File.open(fixture_file("empty.html"))
54
63
  assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "").spoofed?
55
64
  end
65
+
66
+ it 'does allow array as :content_type_mappings' do
67
+ begin
68
+ Paperclip.options[:content_type_mappings] = {
69
+ html: ['binary', 'text/html']
70
+ }
71
+ file = File.open(fixture_file('empty.html'))
72
+ spoofed = Paperclip::MediaTypeSpoofDetector
73
+ .using(file, "empty.html", "text/html").spoofed?
74
+ assert !spoofed
75
+ ensure
76
+ Paperclip.options[:content_type_mappings] = {}
77
+ end
78
+ end
56
79
  end
@@ -20,7 +20,7 @@ describe Paperclip do
20
20
  it "saves Cocaine::CommandLine.path that set before" do
21
21
  Cocaine::CommandLine.path = "/opt/my_app/bin"
22
22
  Paperclip.run("convert", "stuff")
23
- assert_equal [Cocaine::CommandLine.path].flatten.include?("/opt/my_app/bin"), true
23
+ expect(Cocaine::CommandLine.path).to match("/opt/my_app/bin")
24
24
  end
25
25
 
26
26
  it "does not duplicate Cocaine::CommandLine.path on multiple runs" do
@@ -29,7 +29,9 @@ describe Paperclip do
29
29
  Paperclip.options[:command_path] = "/opt/my_app/bin"
30
30
  Paperclip.run("convert", "stuff")
31
31
  Paperclip.run("convert", "more_stuff")
32
- assert_equal 1, [Cocaine::CommandLine.path].flatten.size
32
+
33
+ cmd_path = Paperclip.options[:command_path]
34
+ assert_equal 1, Cocaine::CommandLine.path.scan(cmd_path).count
33
35
  end
34
36
  end
35
37
 
@@ -123,33 +125,6 @@ describe Paperclip do
123
125
  end
124
126
  end
125
127
 
126
- if using_protected_attributes?
127
- context "that is attr_protected" do
128
- before do
129
- Dummy.class_eval do
130
- attr_protected :avatar
131
- end
132
- @dummy = Dummy.new
133
- end
134
-
135
- it "does not assign the avatar on mass-set" do
136
- @dummy.attributes = { other: "I'm set!",
137
- avatar: @file }
138
-
139
- assert_equal "I'm set!", @dummy.other
140
- assert ! @dummy.avatar?
141
- end
142
-
143
- it "allows assigment on normal set" do
144
- @dummy.other = "I'm set!"
145
- @dummy.avatar = @file
146
-
147
- assert_equal "I'm set!", @dummy.other
148
- assert @dummy.avatar?
149
- end
150
- end
151
- end
152
-
153
128
  context "with a subclass" do
154
129
  before do
155
130
  class ::SubDummy < Dummy; end
@@ -3,34 +3,35 @@ require 'spec_helper'
3
3
  describe 'Plural cache' do
4
4
  it 'caches pluralizations' do
5
5
  cache = Paperclip::Interpolations::PluralCache.new
6
- word = "box"
6
+ symbol = :box
7
7
 
8
- word.expects(:pluralize).returns("boxes").once
9
-
10
- cache.pluralize(word)
11
- cache.pluralize(word)
8
+ first = cache.pluralize_symbol(symbol)
9
+ second = cache.pluralize_symbol(symbol)
10
+ expect(first).to equal(second)
12
11
  end
13
12
 
14
13
  it 'caches pluralizations and underscores' do
14
+ class BigBox ; end
15
15
  cache = Paperclip::Interpolations::PluralCache.new
16
- word = "BigBox"
17
-
18
- word.expects(:pluralize).returns(word).once
19
- word.expects(:underscore).returns(word).once
16
+ klass = BigBox
20
17
 
21
- cache.underscore_and_pluralize(word)
22
- cache.underscore_and_pluralize(word)
18
+ first = cache.underscore_and_pluralize_class(klass)
19
+ second = cache.underscore_and_pluralize_class(klass)
20
+ expect(first).to equal(second)
23
21
  end
24
22
 
25
23
  it 'pluralizes words' do
26
24
  cache = Paperclip::Interpolations::PluralCache.new
27
- word = "box"
28
- assert_equal "boxes", cache.pluralize(word)
25
+ symbol = :box
26
+
27
+ expect(cache.pluralize_symbol(symbol)).to eq("boxes")
29
28
  end
30
29
 
31
- it 'pluralizes and underscore words' do
30
+ it 'pluralizes and underscore class names' do
31
+ class BigBox ; end
32
32
  cache = Paperclip::Interpolations::PluralCache.new
33
- word = "BigBox"
34
- assert_equal "big_boxes", cache.underscore_and_pluralize(word)
33
+ klass = BigBox
34
+
35
+ expect(cache.underscore_and_pluralize_class(klass)).to eq("big_boxes")
35
36
  end
36
37
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Paperclip::RailsEnvironment do
4
+
5
+ it "returns nil when Rails isn't defined" do
6
+ resetting_rails_to(nil) do
7
+ expect(Paperclip::RailsEnvironment.get).to be_nil
8
+ end
9
+ end
10
+
11
+ it "returns nil when Rails.env isn't defined" do
12
+ resetting_rails_to({}) do
13
+ expect(Paperclip::RailsEnvironment.get).to be_nil
14
+ end
15
+ end
16
+
17
+ it "returns the value of Rails.env if it is set" do
18
+ resetting_rails_to(OpenStruct.new(env: "foo")) do
19
+ expect(Paperclip::RailsEnvironment.get).to eq "foo"
20
+ end
21
+ end
22
+
23
+ def resetting_rails_to(new_value)
24
+ begin
25
+ previous_rails = Object.send(:remove_const, "Rails")
26
+ Object.const_set("Rails", new_value) unless new_value.nil?
27
+ yield
28
+ ensure
29
+ Object.send(:remove_const, "Rails") if Object.const_defined?("Rails")
30
+ Object.const_set("Rails", previous_rails)
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'fog'
2
+ require 'fog/aws'
3
+ require 'fog/local'
3
4
  require 'timecop'
4
5
 
5
6
  describe Paperclip::Storage::Fog do
@@ -182,6 +183,13 @@ describe Paperclip::Storage::Fog do
182
183
  tempfile.close
183
184
  end
184
185
 
186
+ it 'is able to be handled when missing while copying to a local file' do
187
+ tempfile = Tempfile.new("known_location")
188
+ tempfile.binmode
189
+ assert_equal false, @dummy.avatar.copy_to_local_file(:original, tempfile.path)
190
+ tempfile.close
191
+ end
192
+
185
193
  it "passes the content type to the Fog::Storage::AWS::Files instance" do
186
194
  Fog::Storage::AWS::Files.any_instance.expects(:create).with do |hash|
187
195
  hash[:content_type]
@@ -320,6 +328,9 @@ describe Paperclip::Storage::Fog do
320
328
  it "honors the scheme in public url" do
321
329
  assert_match(/^http:\/\//, @dummy.avatar.url)
322
330
  end
331
+ it "honors the scheme in expiring url" do
332
+ assert_match(/^http:\/\//, @dummy.avatar.expiring_url)
333
+ end
323
334
  end
324
335
 
325
336
  context "with scheme not set" do
@@ -334,15 +345,20 @@ describe Paperclip::Storage::Fog do
334
345
  it "provides HTTPS public url" do
335
346
  assert_match(/^https:\/\//, @dummy.avatar.url)
336
347
  end
348
+ it "provides HTTPS expiring url" do
349
+ assert_match(/^https:\/\//, @dummy.avatar.expiring_url)
350
+ end
337
351
  end
338
352
 
339
353
  context "with a valid bucket name for a subdomain" do
354
+ before { @dummy.stubs(:new_record?).returns(false) }
355
+
340
356
  it "provides an url in subdomain style" do
341
357
  assert_match(/^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png/, @dummy.avatar.url)
342
358
  end
343
359
 
344
360
  it "provides an url that expires in subdomain style" do
345
- assert_match(/^http:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
361
+ assert_match(/^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
346
362
  end
347
363
  end
348
364
 
@@ -390,7 +406,7 @@ describe Paperclip::Storage::Fog do
390
406
  end
391
407
 
392
408
  it "provides a url that expires in folder style" do
393
- assert_match(/^http:\/\/s3.amazonaws.com\/this_is_invalid\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
409
+ assert_match(/^https:\/\/s3.amazonaws.com\/this_is_invalid\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
394
410
  end
395
411
 
396
412
  end
@@ -409,6 +425,9 @@ describe Paperclip::Storage::Fog do
409
425
  assert @connection.directories.get(@dynamic_fog_directory).inspect
410
426
  end
411
427
 
428
+ it "provides an url using dynamic bucket name" do
429
+ assert_match(/^https:\/\/dynamicpaperclip.s3.amazonaws.com\/avatars\/5k.png\?\d*$/, @dummy.avatar.url)
430
+ end
412
431
  end
413
432
 
414
433
  context "with a proc for the fog_host evaluating a model method" do
@@ -475,6 +494,25 @@ describe Paperclip::Storage::Fog do
475
494
  assert_equal @dummy.avatar.fog_credentials, @dynamic_fog_credentials
476
495
  end
477
496
  end
497
+
498
+ context "with custom fog_options" do
499
+ before do
500
+ rebuild_model(
501
+ @options.merge(fog_options: { multipart_chunk_size: 104857600 }),
502
+ )
503
+ @dummy = Dummy.new
504
+ @dummy.avatar = @file
505
+ end
506
+
507
+ it "applies the options to the fog #create call" do
508
+ files = stub
509
+ @dummy.avatar.stubs(:directory).returns stub(files: files)
510
+ files.expects(:create).with(
511
+ has_entries(multipart_chunk_size: 104857600),
512
+ )
513
+ @dummy.save
514
+ end
515
+ end
478
516
  end
479
517
 
480
518
  end
@@ -492,6 +530,7 @@ describe Paperclip::Storage::Fog do
492
530
  @file = File.new(fixture_file('5k.png'), 'rb')
493
531
  @dummy = Dummy.new
494
532
  @dummy.avatar = @file
533
+ @dummy.stubs(:new_record?).returns(false)
495
534
  end
496
535
 
497
536
  after do
@@ -8,6 +8,7 @@ unless ENV["S3_BUCKET"].blank?
8
8
  storage: :s3,
9
9
  bucket: ENV["S3_BUCKET"],
10
10
  path: ":class/:attachment/:id/:style.:extension",
11
+ s3_region: ENV["S3_REGION"],
11
12
  s3_credentials: {
12
13
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
13
14
  aws_secre_access_key: ENV['AWS_SECRET_ACCESS_KEY']
@@ -45,6 +46,7 @@ unless ENV["S3_BUCKET"].blank?
45
46
  storage: :s3,
46
47
  bucket: ENV["S3_BUCKET"],
47
48
  path: ":class/:attachment/:id/:style.:extension",
49
+ s3_region: ENV["S3_REGION"],
48
50
  s3_credentials: {
49
51
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
50
52
  aws_secre_access_key: ENV['AWS_SECRET_ACCESS_KEY']
@@ -64,6 +66,7 @@ unless ENV["S3_BUCKET"].blank?
64
66
  storage: :s3,
65
67
  bucket: ENV["S3_BUCKET"],
66
68
  path: ":class/:attachment/:id/:style.:extension",
69
+ s3_region: ENV["S3_REGION"],
67
70
  s3_credentials: {
68
71
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
69
72
  aws_secre_access_key: ENV['AWS_SECRET_ACCESS_KEY']
@@ -105,6 +108,7 @@ unless ENV["S3_BUCKET"].blank?
105
108
  rebuild_model styles: { thumb: "100x100", square: "32x32#" },
106
109
  storage: :s3,
107
110
  bucket: ENV["S3_BUCKET"],
111
+ s3_region: ENV["S3_REGION"],
108
112
  s3_credentials: {
109
113
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
110
114
  aws_secre_access_key: ENV['AWS_SECRET_ACCESS_KEY']
@@ -136,7 +140,7 @@ unless ENV["S3_BUCKET"].blank?
136
140
  it "is destroyable" do
137
141
  url = @dummy.avatar.url
138
142
  @dummy.destroy
139
- assert_not_found_response url
143
+ assert_forbidden_response url
140
144
  end
141
145
  end
142
146
 
@@ -146,12 +150,12 @@ unless ENV["S3_BUCKET"].blank?
146
150
  storage: :s3,
147
151
  bucket: ENV["S3_BUCKET"],
148
152
  path: ":class/:attachment/:id/:style.:extension",
153
+ s3_region: ENV["S3_REGION"],
149
154
  s3_credentials: {
150
155
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
151
156
  aws_secre_access_key: ENV['AWS_SECRET_ACCESS_KEY']
152
157
  },
153
- s3_server_side_encryption: :aes256
154
-
158
+ s3_server_side_encryption: "AES256"
155
159
  Dummy.delete_all
156
160
  @dummy = Dummy.new
157
161
  end
@@ -173,7 +177,7 @@ unless ENV["S3_BUCKET"].blank?
173
177
  end
174
178
 
175
179
  it "is encrypted on S3" do
176
- assert @dummy.avatar.s3_object.server_side_encryption == :aes256
180
+ assert @dummy.avatar.s3_object.server_side_encryption == "AES256"
177
181
  end
178
182
  end
179
183
  end