paperclip 4.2.2 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +3 -0
  4. data/.hound.yml +1055 -0
  5. data/.rubocop.yml +1 -0
  6. data/.travis.yml +17 -15
  7. data/Appraisals +4 -16
  8. data/CONTRIBUTING.md +19 -8
  9. data/Gemfile +5 -9
  10. data/LICENSE +1 -1
  11. data/MIGRATING-ES.md +317 -0
  12. data/MIGRATING.md +375 -0
  13. data/NEWS +184 -31
  14. data/README.md +371 -201
  15. data/RELEASING.md +17 -0
  16. data/Rakefile +2 -2
  17. data/UPGRADING +12 -9
  18. data/features/basic_integration.feature +10 -6
  19. data/features/migration.feature +0 -24
  20. data/features/step_definitions/attachment_steps.rb +41 -35
  21. data/features/step_definitions/html_steps.rb +2 -2
  22. data/features/step_definitions/rails_steps.rb +39 -38
  23. data/features/step_definitions/s3_steps.rb +2 -2
  24. data/features/step_definitions/web_steps.rb +1 -103
  25. data/features/support/env.rb +1 -0
  26. data/features/support/file_helpers.rb +2 -2
  27. data/features/support/paths.rb +1 -1
  28. data/features/support/rails.rb +0 -24
  29. data/gemfiles/4.2.gemfile +6 -8
  30. data/gemfiles/5.0.gemfile +17 -0
  31. data/lib/generators/paperclip/paperclip_generator.rb +9 -1
  32. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
  33. data/lib/paperclip/attachment.rb +51 -26
  34. data/lib/paperclip/attachment_registry.rb +3 -2
  35. data/lib/paperclip/callbacks.rb +8 -6
  36. data/lib/paperclip/content_type_detector.rb +27 -11
  37. data/lib/paperclip/errors.rb +3 -1
  38. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  39. data/lib/paperclip/filename_cleaner.rb +0 -1
  40. data/lib/paperclip/geometry_detector_factory.rb +3 -3
  41. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  42. data/lib/paperclip/glue.rb +1 -1
  43. data/lib/paperclip/has_attached_file.rb +9 -2
  44. data/lib/paperclip/helpers.rb +15 -11
  45. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  46. data/lib/paperclip/interpolations.rb +24 -14
  47. data/lib/paperclip/io_adapters/abstract_adapter.rb +32 -4
  48. data/lib/paperclip/io_adapters/attachment_adapter.rb +17 -6
  49. data/lib/paperclip/io_adapters/data_uri_adapter.rb +8 -8
  50. data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
  51. data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
  52. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +8 -7
  53. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
  54. data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
  55. data/lib/paperclip/io_adapters/registry.rb +6 -2
  56. data/lib/paperclip/io_adapters/stringio_adapter.rb +9 -6
  57. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
  58. data/lib/paperclip/io_adapters/uri_adapter.rb +43 -19
  59. data/lib/paperclip/logger.rb +1 -1
  60. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  61. data/lib/paperclip/media_type_spoof_detector.rb +13 -9
  62. data/lib/paperclip/processor.rb +15 -6
  63. data/lib/paperclip/rails_environment.rb +25 -0
  64. data/lib/paperclip/schema.rb +4 -10
  65. data/lib/paperclip/storage/filesystem.rb +13 -2
  66. data/lib/paperclip/storage/fog.rb +33 -20
  67. data/lib/paperclip/storage/s3.rb +89 -70
  68. data/lib/paperclip/style.rb +0 -1
  69. data/lib/paperclip/thumbnail.rb +24 -12
  70. data/lib/paperclip/url_generator.rb +17 -13
  71. data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
  72. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +4 -0
  73. data/lib/paperclip/validators.rb +1 -1
  74. data/lib/paperclip/version.rb +3 -1
  75. data/lib/paperclip.rb +27 -13
  76. data/lib/tasks/paperclip.rake +33 -3
  77. data/paperclip.gemspec +18 -15
  78. data/spec/paperclip/attachment_definitions_spec.rb +1 -1
  79. data/spec/paperclip/attachment_processing_spec.rb +2 -5
  80. data/spec/paperclip/attachment_registry_spec.rb +84 -13
  81. data/spec/paperclip/attachment_spec.rb +147 -41
  82. data/spec/paperclip/content_type_detector_spec.rb +9 -2
  83. data/spec/paperclip/file_command_content_type_detector_spec.rb +15 -2
  84. data/spec/paperclip/filename_cleaner_spec.rb +0 -1
  85. data/spec/paperclip/geometry_spec.rb +1 -1
  86. data/spec/paperclip/glue_spec.rb +44 -0
  87. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  88. data/spec/paperclip/integration_spec.rb +42 -5
  89. data/spec/paperclip/interpolations_spec.rb +21 -9
  90. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +106 -23
  91. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +6 -3
  92. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +7 -1
  93. data/spec/paperclip/io_adapters/file_adapter_spec.rb +6 -3
  94. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +51 -14
  95. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
  96. data/spec/paperclip/io_adapters/registry_spec.rb +2 -2
  97. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +5 -1
  98. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +5 -5
  99. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +126 -8
  100. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
  101. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +1 -1
  102. data/spec/paperclip/media_type_spoof_detector_spec.rb +75 -11
  103. data/spec/paperclip/paperclip_spec.rb +15 -40
  104. data/spec/paperclip/plural_cache_spec.rb +17 -16
  105. data/spec/paperclip/processor_spec.rb +4 -4
  106. data/spec/paperclip/rails_environment_spec.rb +33 -0
  107. data/spec/paperclip/schema_spec.rb +46 -46
  108. data/spec/paperclip/storage/fog_spec.rb +63 -3
  109. data/spec/paperclip/storage/s3_live_spec.rb +20 -14
  110. data/spec/paperclip/storage/s3_spec.rb +400 -215
  111. data/spec/paperclip/style_spec.rb +0 -1
  112. data/spec/paperclip/tempfile_factory_spec.rb +4 -0
  113. data/spec/paperclip/tempfile_spec.rb +35 -0
  114. data/spec/paperclip/thumbnail_spec.rb +59 -38
  115. data/spec/paperclip/url_generator_spec.rb +55 -45
  116. data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
  117. data/spec/paperclip/validators_spec.rb +5 -5
  118. data/spec/spec_helper.rb +7 -1
  119. data/spec/support/assertions.rb +12 -1
  120. data/spec/support/fake_model.rb +4 -0
  121. data/spec/support/fixtures/empty.xlsx +0 -0
  122. data/spec/support/matchers/have_column.rb +11 -2
  123. data/spec/support/mock_attachment.rb +2 -0
  124. data/spec/support/mock_url_generator_builder.rb +2 -2
  125. data/spec/support/model_reconstruction.rb +11 -3
  126. data/spec/support/reporting.rb +11 -0
  127. metadata +110 -63
  128. data/RUNNING_TESTS.md +0 -4
  129. data/cucumber/paperclip_steps.rb +0 -6
  130. data/gemfiles/3.2.gemfile +0 -19
  131. data/gemfiles/4.0.gemfile +0 -19
  132. data/gemfiles/4.1.gemfile +0 -19
  133. data/lib/paperclip/locales/de.yml +0 -18
  134. data/lib/paperclip/locales/es.yml +0 -18
  135. data/lib/paperclip/locales/ja.yml +0 -18
  136. data/lib/paperclip/locales/pt-BR.yml +0 -18
  137. data/lib/paperclip/locales/zh-CN.yml +0 -18
  138. data/lib/paperclip/locales/zh-HK.yml +0 -18
  139. data/lib/paperclip/locales/zh-TW.yml +0 -18
  140. data/spec/support/mock_model.rb +0 -2
  141. data/spec/support/rails_helpers.rb +0 -7
@@ -1,13 +1,29 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Paperclip::UriAdapter do
4
+ let(:content_type) { "image/png" }
5
+ let(:meta) { {} }
6
+
7
+ before do
8
+ @open_return = StringIO.new("xxx")
9
+ @open_return.stubs(:content_type).returns(content_type)
10
+ @open_return.stubs(:meta).returns(meta)
11
+ Paperclip::UriAdapter.register
12
+ end
13
+
14
+ after do
15
+ Paperclip.io_adapters.unregister(described_class)
16
+ end
17
+
4
18
  context "a new instance" do
19
+ let(:meta) { { "content-type" => "image/png" } }
20
+
5
21
  before do
6
- @open_return = StringIO.new("xxx")
7
- @open_return.stubs(:content_type).returns("image/png")
8
- Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(@open_return)
22
+ Paperclip::UriAdapter.any_instance.
23
+ stubs(:download_content).returns(@open_return)
24
+
9
25
  @uri = URI.parse("http://thoughtbot.com/images/thoughtbot-logo.png")
10
- @subject = Paperclip.io_adapters.for(@uri)
26
+ @subject = Paperclip.io_adapters.for(@uri, hash_digest: Digest::MD5)
11
27
  end
12
28
 
13
29
  it "returns a file name" do
@@ -48,7 +64,7 @@ describe Paperclip::UriAdapter do
48
64
  assert_equal 'image/png', @subject.content_type
49
65
  end
50
66
 
51
- it 'accepts an orgiginal_filename' do
67
+ it "accepts an original_filename" do
52
68
  @subject.original_filename = 'image.png'
53
69
  assert_equal 'image.png', @subject.original_filename
54
70
  end
@@ -56,8 +72,13 @@ describe Paperclip::UriAdapter do
56
72
  end
57
73
 
58
74
  context "a directory index url" do
75
+ let(:content_type) { "text/html" }
76
+ let(:meta) { { "content-type" => "text/html" } }
77
+
59
78
  before do
60
- Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
79
+ Paperclip::UriAdapter.any_instance.
80
+ stubs(:download_content).returns(@open_return)
81
+
61
82
  @uri = URI.parse("http://thoughtbot.com")
62
83
  @subject = Paperclip.io_adapters.for(@uri)
63
84
  end
@@ -73,7 +94,9 @@ describe Paperclip::UriAdapter do
73
94
 
74
95
  context "a url with query params" do
75
96
  before do
76
- Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
97
+ Paperclip::UriAdapter.any_instance.
98
+ stubs(:download_content).returns(@open_return)
99
+
77
100
  @uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
78
101
  @subject = Paperclip.io_adapters.for(@uri)
79
102
  end
@@ -83,9 +106,77 @@ describe Paperclip::UriAdapter do
83
106
  end
84
107
  end
85
108
 
109
+ context "a url with content disposition headers" do
110
+ let(:file_name) { "test_document.pdf" }
111
+ let(:filename_from_path) { "paperclip" }
112
+
113
+ before do
114
+ Paperclip::UriAdapter.any_instance.
115
+ stubs(:download_content).returns(@open_return)
116
+
117
+ @uri = URI.parse(
118
+ "https://github.com/thoughtbot/#{filename_from_path}?file=test")
119
+ end
120
+
121
+ it "returns file name from path" do
122
+ meta["content-disposition"] = "inline;"
123
+
124
+ @subject = Paperclip.io_adapters.for(@uri)
125
+
126
+ assert_equal filename_from_path, @subject.original_filename
127
+ end
128
+
129
+ it "returns a file name enclosed in double quotes" do
130
+ file_name = "john's test document.pdf"
131
+ meta["content-disposition"] = "attachment; filename=\"#{file_name}\";"
132
+
133
+ @subject = Paperclip.io_adapters.for(@uri)
134
+
135
+ assert_equal file_name, @subject.original_filename
136
+ end
137
+
138
+ it "returns a file name not enclosed in double quotes" do
139
+ meta["content-disposition"] = "ATTACHMENT; FILENAME=#{file_name};"
140
+
141
+ @subject = Paperclip.io_adapters.for(@uri)
142
+
143
+ assert_equal file_name, @subject.original_filename
144
+ end
145
+
146
+ it "does not crash when an empty filename is given" do
147
+ meta["content-disposition"] = "ATTACHMENT; FILENAME=\"\";"
148
+
149
+ @subject = Paperclip.io_adapters.for(@uri)
150
+
151
+ assert_equal "", @subject.original_filename
152
+ end
153
+
154
+ it "returns a file name ignoring RFC 5987 encoding" do
155
+ meta["content-disposition"] =
156
+ "attachment; filename=#{file_name}; filename* = utf-8''%e2%82%ac%20rates"
157
+
158
+ @subject = Paperclip.io_adapters.for(@uri)
159
+
160
+ assert_equal file_name, @subject.original_filename
161
+ end
162
+
163
+ context "when file name has consecutive periods" do
164
+ let(:file_name) { "test_document..pdf" }
165
+
166
+ it "returns a file name" do
167
+ @uri = URI.parse(
168
+ "https://github.com/thoughtbot/#{file_name}?file=test")
169
+ @subject = Paperclip.io_adapters.for(@uri)
170
+ assert_equal file_name, @subject.original_filename
171
+ end
172
+ end
173
+ end
174
+
86
175
  context "a url with restricted characters in the filename" do
87
176
  before do
88
- Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
177
+ Paperclip::UriAdapter.any_instance.
178
+ stubs(:download_content).returns(@open_return)
179
+
89
180
  @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
90
181
  @subject = Paperclip.io_adapters.for(@uri)
91
182
  end
@@ -99,4 +190,31 @@ describe Paperclip::UriAdapter do
99
190
  end
100
191
  end
101
192
 
193
+ describe "#download_content" do
194
+ before do
195
+ Paperclip::UriAdapter.any_instance.stubs(:open).returns(@open_return)
196
+ @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
197
+ @subject = Paperclip.io_adapters.for(@uri)
198
+ end
199
+
200
+ after do
201
+ @subject.send(:download_content)
202
+ end
203
+
204
+ context "with default read_timeout" do
205
+ it "calls open without options" do
206
+ @subject.expects(:open).with(@uri, {}).at_least_once
207
+ end
208
+ end
209
+
210
+ context "with custom read_timeout" do
211
+ before do
212
+ Paperclip.options[:read_timeout] = 120
213
+ end
214
+
215
+ it "calls open with read_timeout option" do
216
+ @subject.expects(:open).with(@uri, read_timeout: 120).at_least_once
217
+ end
218
+ end
219
+ end
102
220
  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
 
@@ -7,7 +7,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentSizeMatcher do
7
7
  before do
8
8
  reset_table("dummies") do |d|
9
9
  d.string :avatar_file_name
10
- d.integer :avatar_file_size
10
+ d.bigint :avatar_file_size
11
11
  end
12
12
  reset_class "Dummy"
13
13
  Dummy.do_not_validate_attachment_file_type :avatar
@@ -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,83 @@ 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
59
+ end
60
+
61
+ context "GIF file named without extension, but we're told GIF" do
62
+ let(:file) { File.open(fixture_file("animated")) }
63
+ let(:spoofed?) do
64
+ Paperclip::MediaTypeSpoofDetector.
65
+ using(file, "animated", "image/gif").
66
+ spoofed?
67
+ end
68
+
69
+ it "accepts the file" do
70
+ assert !spoofed?
71
+ end
50
72
  end
51
73
 
52
- it "does not reject is content_type is empty but otherwise checks out" do
74
+ context "GIF file named without extension, but we're told HTML" do
75
+ let(:file) { File.open(fixture_file("animated")) }
76
+ let(:spoofed?) do
77
+ Paperclip::MediaTypeSpoofDetector.
78
+ using(file, "animated", "text/html").
79
+ spoofed?
80
+ end
81
+
82
+ it "rejects the file" do
83
+ assert spoofed?
84
+ end
85
+ end
86
+
87
+ it "does not reject if content_type is empty but otherwise checks out" do
53
88
  file = File.open(fixture_file("empty.html"))
54
89
  assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "").spoofed?
55
90
  end
91
+
92
+ it 'does allow array as :content_type_mappings' do
93
+ begin
94
+ Paperclip.options[:content_type_mappings] = {
95
+ html: ['binary', 'text/html']
96
+ }
97
+ file = File.open(fixture_file('empty.html'))
98
+ spoofed = Paperclip::MediaTypeSpoofDetector
99
+ .using(file, "empty.html", "text/html").spoofed?
100
+ assert !spoofed
101
+ ensure
102
+ Paperclip.options[:content_type_mappings] = {}
103
+ end
104
+ end
105
+
106
+ context "#type_from_file_command" do
107
+ let(:file) { File.new(fixture_file("empty.html")) }
108
+ let(:detector) { Paperclip::MediaTypeSpoofDetector.new(file, "html", "") }
109
+
110
+ it "does work with the output of old versions of file" do
111
+ Paperclip.stubs(:run).returns("text/html charset=us-ascii")
112
+ expect(detector.send(:type_from_file_command)).to eq("text/html")
113
+ end
114
+
115
+ it "does work with the output of new versions of file" do
116
+ Paperclip.stubs(:run).returns("text/html; charset=us-ascii")
117
+ expect(detector.send(:type_from_file_command)).to eq("text/html")
118
+ end
119
+ end
56
120
  end
@@ -4,38 +4,40 @@ describe Paperclip do
4
4
  context ".run" do
5
5
  before do
6
6
  Paperclip.options[:log_command] = false
7
- Cocaine::CommandLine.expects(:new).with("convert", "stuff", {}).returns(stub(:run))
8
- @original_command_line_path = Cocaine::CommandLine.path
7
+ Terrapin::CommandLine.expects(:new).with("convert", "stuff", {}).returns(stub(:run))
8
+ @original_command_line_path = Terrapin::CommandLine.path
9
9
  end
10
10
 
11
11
  after do
12
12
  Paperclip.options[:log_command] = true
13
- Cocaine::CommandLine.path = @original_command_line_path
13
+ Terrapin::CommandLine.path = @original_command_line_path
14
14
  end
15
15
 
16
- it "runs the command with Cocaine" do
16
+ it "runs the command with Terrapin" do
17
17
  Paperclip.run("convert", "stuff")
18
18
  end
19
19
 
20
- it "saves Cocaine::CommandLine.path that set before" do
21
- Cocaine::CommandLine.path = "/opt/my_app/bin"
20
+ it "saves Terrapin::CommandLine.path that set before" do
21
+ Terrapin::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(Terrapin::CommandLine.path).to match("/opt/my_app/bin")
24
24
  end
25
25
 
26
- it "does not duplicate Cocaine::CommandLine.path on multiple runs" do
27
- Cocaine::CommandLine.expects(:new).with("convert", "more_stuff", {}).returns(stub(:run))
28
- Cocaine::CommandLine.path = nil
26
+ it "does not duplicate Terrapin::CommandLine.path on multiple runs" do
27
+ Terrapin::CommandLine.expects(:new).with("convert", "more_stuff", {}).returns(stub(:run))
28
+ Terrapin::CommandLine.path = nil
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, Terrapin::CommandLine.path.scan(cmd_path).count
33
35
  end
34
36
  end
35
37
 
36
38
  it 'does not raise errors when doing a lot of running' do
37
39
  Paperclip.options[:command_path] = ["/usr/local/bin"] * 1024
38
- Cocaine::CommandLine.path = "/something/else"
40
+ Terrapin::CommandLine.path = "/something/else"
39
41
  100.times do |x|
40
42
  Paperclip.run("echo", x.to_s)
41
43
  end
@@ -61,7 +63,7 @@ describe Paperclip do
61
63
  context "Calling Paperclip.run with a logger" do
62
64
  it "passes the defined logger if :log_command is set" do
63
65
  Paperclip.options[:log_command] = true
64
- Cocaine::CommandLine.expects(:new).with("convert", "stuff", logger: Paperclip.logger).returns(stub(:run))
66
+ Terrapin::CommandLine.expects(:new).with("convert", "stuff", logger: Paperclip.logger).returns(stub(:run))
65
67
  Paperclip.run("convert", "stuff")
66
68
  end
67
69
  end
@@ -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
@@ -9,17 +9,17 @@ describe Paperclip::Processor do
9
9
  end
10
10
 
11
11
  context "Calling #convert" do
12
- it "runs the convert command with Cocaine" do
12
+ it "runs the convert command with Terrapin" do
13
13
  Paperclip.options[:log_command] = false
14
- Cocaine::CommandLine.expects(:new).with("convert", "stuff", {}).returns(stub(:run))
14
+ Terrapin::CommandLine.expects(:new).with("convert", "stuff", {}).returns(stub(:run))
15
15
  Paperclip::Processor.new('filename').convert("stuff")
16
16
  end
17
17
  end
18
18
 
19
19
  context "Calling #identify" do
20
- it "runs the identify command with Cocaine" do
20
+ it "runs the identify command with Terrapin" do
21
21
  Paperclip.options[:log_command] = false
22
- Cocaine::CommandLine.expects(:new).with("identify", "stuff", {}).returns(stub(:run))
22
+ Terrapin::CommandLine.expects(:new).with("identify", "stuff", {}).returns(stub(:run))
23
23
  Paperclip::Processor.new('filename').identify("stuff")
24
24
  end
25
25
  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