paperclip 3.4.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +3 -0
  4. data/.gitignore +0 -6
  5. data/.hound.yml +1055 -0
  6. data/.rubocop.yml +1 -0
  7. data/.travis.yml +19 -12
  8. data/Appraisals +4 -11
  9. data/CONTRIBUTING.md +29 -13
  10. data/Gemfile +13 -4
  11. data/LICENSE +1 -3
  12. data/MIGRATING-ES.md +317 -0
  13. data/MIGRATING.md +375 -0
  14. data/NEWS +390 -71
  15. data/README.md +607 -152
  16. data/RELEASING.md +17 -0
  17. data/Rakefile +6 -8
  18. data/UPGRADING +12 -9
  19. data/features/basic_integration.feature +34 -21
  20. data/features/migration.feature +0 -24
  21. data/features/rake_tasks.feature +2 -3
  22. data/features/step_definitions/attachment_steps.rb +44 -36
  23. data/features/step_definitions/html_steps.rb +2 -2
  24. data/features/step_definitions/rails_steps.rb +125 -26
  25. data/features/step_definitions/s3_steps.rb +3 -3
  26. data/features/step_definitions/web_steps.rb +1 -103
  27. data/features/support/env.rb +3 -2
  28. data/features/support/fakeweb.rb +4 -1
  29. data/features/support/file_helpers.rb +12 -2
  30. data/features/support/fixtures/gemfile.txt +1 -1
  31. data/features/support/paths.rb +1 -1
  32. data/features/support/rails.rb +4 -11
  33. data/gemfiles/4.2.gemfile +17 -0
  34. data/gemfiles/5.0.gemfile +17 -0
  35. data/lib/generators/paperclip/paperclip_generator.rb +9 -3
  36. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +2 -2
  37. data/lib/paperclip/attachment.rb +215 -82
  38. data/lib/paperclip/attachment_registry.rb +60 -0
  39. data/lib/paperclip/callbacks.rb +13 -1
  40. data/lib/paperclip/content_type_detector.rb +48 -24
  41. data/lib/paperclip/errors.rb +8 -1
  42. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  43. data/lib/paperclip/filename_cleaner.rb +15 -0
  44. data/lib/paperclip/geometry_detector_factory.rb +12 -5
  45. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  46. data/lib/paperclip/glue.rb +1 -2
  47. data/lib/paperclip/has_attached_file.rb +115 -0
  48. data/lib/paperclip/helpers.rb +15 -20
  49. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  50. data/lib/paperclip/interpolations.rb +36 -14
  51. data/lib/paperclip/io_adapters/abstract_adapter.rb +42 -5
  52. data/lib/paperclip/io_adapters/attachment_adapter.rb +20 -9
  53. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  54. data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
  55. data/lib/paperclip/io_adapters/file_adapter.rb +13 -7
  56. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
  57. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
  58. data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
  59. data/lib/paperclip/io_adapters/registry.rb +6 -2
  60. data/lib/paperclip/io_adapters/stringio_adapter.rb +15 -16
  61. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +11 -7
  62. data/lib/paperclip/io_adapters/uri_adapter.rb +43 -19
  63. data/lib/paperclip/locales/en.yml +1 -0
  64. data/lib/paperclip/logger.rb +1 -1
  65. data/lib/paperclip/matchers/have_attached_file_matcher.rb +3 -6
  66. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  67. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +7 -2
  68. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  69. data/lib/paperclip/matchers.rb +1 -1
  70. data/lib/paperclip/media_type_spoof_detector.rb +93 -0
  71. data/lib/paperclip/missing_attachment_styles.rb +11 -16
  72. data/lib/paperclip/processor.rb +15 -43
  73. data/lib/paperclip/processor_helpers.rb +50 -0
  74. data/lib/paperclip/rails_environment.rb +25 -0
  75. data/lib/paperclip/schema.rb +10 -8
  76. data/lib/paperclip/storage/filesystem.rb +20 -5
  77. data/lib/paperclip/storage/fog.rb +49 -23
  78. data/lib/paperclip/storage/s3.rb +153 -82
  79. data/lib/paperclip/style.rb +8 -3
  80. data/lib/paperclip/tempfile_factory.rb +6 -4
  81. data/lib/paperclip/thumbnail.rb +35 -19
  82. data/lib/paperclip/url_generator.rb +26 -14
  83. data/lib/paperclip/validators/attachment_content_type_validator.rb +15 -2
  84. data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
  85. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
  86. data/lib/paperclip/validators/attachment_presence_validator.rb +12 -8
  87. data/lib/paperclip/validators/attachment_size_validator.rb +17 -10
  88. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +31 -0
  89. data/lib/paperclip/validators.rb +31 -3
  90. data/lib/paperclip/version.rb +3 -1
  91. data/lib/paperclip.rb +41 -55
  92. data/lib/tasks/paperclip.rake +56 -9
  93. data/paperclip.gemspec +18 -17
  94. data/shoulda_macros/paperclip.rb +13 -3
  95. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  96. data/spec/paperclip/attachment_processing_spec.rb +79 -0
  97. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  98. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +597 -389
  99. data/spec/paperclip/content_type_detector_spec.rb +48 -0
  100. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  101. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  102. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  103. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  104. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +50 -52
  105. data/spec/paperclip/glue_spec.rb +44 -0
  106. data/spec/paperclip/has_attached_file_spec.rb +158 -0
  107. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +179 -199
  108. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +79 -46
  109. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  110. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +54 -25
  111. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +89 -0
  112. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  113. data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
  114. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +138 -0
  115. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  116. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  117. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +12 -9
  118. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  119. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  120. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +220 -0
  121. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  122. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +109 -0
  123. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  124. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  125. data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
  126. data/spec/paperclip/meta_class_spec.rb +30 -0
  127. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  128. data/spec/paperclip/paperclip_spec.rb +192 -0
  129. data/spec/paperclip/plural_cache_spec.rb +37 -0
  130. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  131. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +7 -7
  132. data/spec/paperclip/rails_environment_spec.rb +33 -0
  133. data/spec/paperclip/rake_spec.rb +103 -0
  134. data/spec/paperclip/schema_spec.rb +248 -0
  135. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  136. data/spec/paperclip/storage/fog_spec.rb +566 -0
  137. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  138. data/spec/paperclip/storage/s3_spec.rb +1693 -0
  139. data/spec/paperclip/style_spec.rb +254 -0
  140. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  141. data/spec/paperclip/tempfile_spec.rb +35 -0
  142. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +186 -141
  143. data/spec/paperclip/url_generator_spec.rb +221 -0
  144. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  145. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  146. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +20 -20
  147. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +87 -59
  148. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  149. data/spec/paperclip/validators_spec.rb +164 -0
  150. data/spec/spec_helper.rb +46 -0
  151. data/spec/support/assertions.rb +82 -0
  152. data/spec/support/fake_model.rb +25 -0
  153. data/spec/support/fake_rails.rb +12 -0
  154. data/spec/support/fixtures/empty.html +1 -0
  155. data/spec/support/fixtures/empty.xlsx +0 -0
  156. data/spec/support/fixtures/spaced file.jpg +0 -0
  157. data/spec/support/matchers/accept.rb +5 -0
  158. data/spec/support/matchers/exist.rb +5 -0
  159. data/spec/support/matchers/have_column.rb +23 -0
  160. data/{test → spec}/support/mock_attachment.rb +2 -0
  161. data/{test → spec}/support/mock_url_generator_builder.rb +2 -2
  162. data/spec/support/model_reconstruction.rb +68 -0
  163. data/spec/support/reporting.rb +11 -0
  164. data/spec/support/test_data.rb +13 -0
  165. data/spec/support/version_helper.rb +9 -0
  166. metadata +395 -346
  167. data/Gemfile.lock +0 -200
  168. data/RUNNING_TESTS.md +0 -4
  169. data/cucumber/paperclip_steps.rb +0 -6
  170. data/gemfiles/3.0.gemfile +0 -11
  171. data/gemfiles/3.1.gemfile +0 -11
  172. data/gemfiles/3.2.gemfile +0 -11
  173. data/lib/paperclip/attachment_options.rb +0 -9
  174. data/lib/paperclip/instance_methods.rb +0 -35
  175. data/test/attachment_options_test.rb +0 -27
  176. data/test/attachment_processing_test.rb +0 -29
  177. data/test/content_type_detector_test.rb +0 -40
  178. data/test/file_command_content_type_detector_test.rb +0 -25
  179. data/test/generator_test.rb +0 -80
  180. data/test/geometry_detector_test.rb +0 -24
  181. data/test/helper.rb +0 -199
  182. data/test/io_adapters/abstract_adapter_test.rb +0 -50
  183. data/test/io_adapters/file_adapter_test.rb +0 -100
  184. data/test/io_adapters/identity_adapter_test.rb +0 -8
  185. data/test/io_adapters/stringio_adapter_test.rb +0 -51
  186. data/test/io_adapters/uploaded_file_adapter_test.rb +0 -123
  187. data/test/io_adapters/uri_adapter_test.rb +0 -86
  188. data/test/matchers/have_attached_file_matcher_test.rb +0 -24
  189. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -110
  190. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -47
  191. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -86
  192. data/test/meta_class_test.rb +0 -32
  193. data/test/paperclip_missing_attachment_styles_test.rb +0 -94
  194. data/test/paperclip_test.rb +0 -259
  195. data/test/schema_test.rb +0 -200
  196. data/test/storage/fog_test.rb +0 -453
  197. data/test/storage/s3_live_test.rb +0 -179
  198. data/test/storage/s3_test.rb +0 -1236
  199. data/test/style_test.rb +0 -213
  200. data/test/support/mock_model.rb +0 -2
  201. data/test/tempfile_factory_test.rb +0 -13
  202. data/test/url_generator_test.rb +0 -187
  203. data/test/validators/attachment_content_type_validator_test.rb +0 -292
  204. data/test/validators_test.rb +0 -25
  205. /data/{test → spec}/database.yml +0 -0
  206. /data/{test → spec/support}/fixtures/12k.png +0 -0
  207. /data/{test → spec/support}/fixtures/50x50.png +0 -0
  208. /data/{test → spec/support}/fixtures/5k.png +0 -0
  209. /data/{test → spec/support}/fixtures/animated +0 -0
  210. /data/{test → spec/support}/fixtures/animated.gif +0 -0
  211. /data/{test → spec/support}/fixtures/animated.unknown +0 -0
  212. /data/{test → spec/support}/fixtures/bad.png +0 -0
  213. /data/{test → spec/support}/fixtures/fog.yml +0 -0
  214. /data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  215. /data/{test → spec/support}/fixtures/s3.yml +0 -0
  216. /data/{test → spec/support}/fixtures/spaced file.png +0 -0
  217. /data/{test → spec/support}/fixtures/text.txt +0 -0
  218. /data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  219. /data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  220. /data/{test → spec}/support/mock_interpolator.rb +0 -0
@@ -1,47 +1,63 @@
1
- # encoding: utf-8
2
-
3
- require './test/helper'
1
+ require 'spec_helper'
4
2
  require 'open-uri'
5
3
 
6
- class IntegrationTest < Test::Unit::TestCase
4
+ describe 'Paperclip' do
5
+ around do |example|
6
+ files_before = ObjectSpace.each_object(Tempfile).select do |file|
7
+ file.path && File.file?(file.path)
8
+ end
9
+
10
+ example.run
11
+
12
+ files_after = ObjectSpace.each_object(Tempfile).select do |file|
13
+ file.path && File.file?(file.path)
14
+ end
15
+
16
+ diff = files_after - files_before
17
+ expect(diff).to eq([]), "Leaked tempfiles: #{diff.inspect}"
18
+ end
19
+
7
20
  context "Many models at once" do
8
- setup do
21
+ before do
9
22
  rebuild_model
10
- @file = File.new(fixture_file("5k.png"), 'rb')
11
- 300.times do |i|
12
- Dummy.create! :avatar => @file
13
- end
23
+ @file = File.new(fixture_file("5k.png"), 'rb')
24
+ # Deals with `Too many open files` error
25
+ dummies = Array.new(300) { Dummy.new avatar: @file }
26
+ Dummy.import dummies
27
+ # save attachment instances to run after hooks including tempfile cleanup
28
+ # since activerecord-import does not use our usually hooked-in hooks
29
+ # (such as after_save)
30
+ dummies.each { |dummy| dummy.avatar.save }
14
31
  end
15
32
 
16
- teardown { @file.close }
33
+ after { @file.close }
17
34
 
18
- should "not exceed the open file limit" do
35
+ it "does not exceed the open file limit" do
19
36
  assert_nothing_raised do
20
- dummies = Dummy.find(:all)
21
- dummies.each { |dummy| dummy.avatar }
37
+ Dummy.all.each { |dummy| dummy.avatar }
22
38
  end
23
39
  end
24
40
  end
25
41
 
26
42
  context "An attachment" do
27
- setup do
28
- rebuild_model :styles => { :thumb => "50x50#" }
43
+ before do
44
+ rebuild_model styles: { thumb: "50x50#" }
29
45
  @dummy = Dummy.new
30
46
  @file = File.new(fixture_file("5k.png"), 'rb')
31
47
  @dummy.avatar = @file
32
48
  assert @dummy.save
33
49
  end
34
50
 
35
- teardown { @file.close }
51
+ after { @file.close }
36
52
 
37
- should "create its thumbnails properly" do
38
- assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
53
+ it "creates its thumbnails properly" do
54
+ assert_match(/\b50x50\b/, `identify "#{@dummy.avatar.path(:thumb)}"`)
39
55
  end
40
56
 
41
57
  context 'reprocessing with unreadable original' do
42
- setup { File.chmod(0000, @dummy.avatar.path) }
58
+ before { File.chmod(0000, @dummy.avatar.path) }
43
59
 
44
- should "not raise an error" do
60
+ it "does not raise an error" do
45
61
  assert_nothing_raised do
46
62
  silence_stream(STDERR) do
47
63
  @dummy.avatar.reprocess!
@@ -49,19 +65,19 @@ class IntegrationTest < Test::Unit::TestCase
49
65
  end
50
66
  end
51
67
 
52
- should "return false" do
68
+ it "returns false" do
53
69
  silence_stream(STDERR) do
54
70
  assert !@dummy.avatar.reprocess!
55
71
  end
56
72
  end
57
73
 
58
- teardown { File.chmod(0644, @dummy.avatar.path) }
74
+ after { File.chmod(0644, @dummy.avatar.path) }
59
75
  end
60
76
 
61
77
  context "redefining its attachment styles" do
62
- setup do
78
+ before do
63
79
  Dummy.class_eval do
64
- has_attached_file :avatar, :styles => { :thumb => "150x25#", :dynamic => lambda { |a| '50x50#' } }
80
+ has_attached_file :avatar, styles: { thumb: "150x25#", dynamic: lambda { |a| '50x50#' } }
65
81
  end
66
82
  @d2 = Dummy.find(@dummy.id)
67
83
  @original_timestamp = @d2.avatar_updated_at
@@ -69,37 +85,37 @@ class IntegrationTest < Test::Unit::TestCase
69
85
  @d2.save
70
86
  end
71
87
 
72
- should "create its thumbnails properly" do
73
- assert_match /\b150x25\b/, `identify "#{@dummy.avatar.path(:thumb)}"`
74
- assert_match /\b50x50\b/, `identify "#{@dummy.avatar.path(:dynamic)}"`
88
+ it "creates its thumbnails properly" do
89
+ assert_match(/\b150x25\b/, `identify "#{@dummy.avatar.path(:thumb)}"`)
90
+ assert_match(/\b50x50\b/, `identify "#{@dummy.avatar.path(:dynamic)}"`)
75
91
  end
76
92
 
77
- should "change the timestamp" do
93
+ it "changes the timestamp" do
78
94
  assert_not_equal @original_timestamp, @d2.avatar_updated_at
79
95
  end
80
96
  end
81
97
  end
82
98
 
83
99
  context "Attachment" do
84
- setup do
100
+ before do
85
101
  @thumb_path = "tmp/public/system/dummies/avatars/000/000/001/thumb/5k.png"
86
- File.delete(@thumb_path) if File.exists?(@thumb_path)
87
- rebuild_model :styles => { :thumb => "50x50#" }
102
+ File.delete(@thumb_path) if File.exist?(@thumb_path)
103
+ rebuild_model styles: { thumb: "50x50#" }
88
104
  @dummy = Dummy.new
89
105
  @file = File.new(fixture_file("5k.png"), 'rb')
90
106
 
91
107
  end
92
108
 
93
- teardown { @file.close }
109
+ after { @file.close }
94
110
 
95
- should "not create the thumbnails upon saving when post-processing is disabled" do
111
+ it "does not create the thumbnails upon saving when post-processing is disabled" do
96
112
  @dummy.avatar.post_processing = false
97
113
  @dummy.avatar = @file
98
114
  assert @dummy.save
99
115
  assert_file_not_exists @thumb_path
100
116
  end
101
117
 
102
- should "create the thumbnails upon saving when post_processing is enabled" do
118
+ it "creates the thumbnails upon saving when post_processing is enabled" do
103
119
  @dummy.avatar.post_processing = true
104
120
  @dummy.avatar = @file
105
121
  assert @dummy.save
@@ -108,12 +124,12 @@ class IntegrationTest < Test::Unit::TestCase
108
124
  end
109
125
 
110
126
  context "Attachment with no generated thumbnails" do
111
- setup do
127
+ before do
112
128
  @thumb_small_path = "tmp/public/system/dummies/avatars/000/000/001/thumb_small/5k.png"
113
129
  @thumb_large_path = "tmp/public/system/dummies/avatars/000/000/001/thumb_large/5k.png"
114
- File.delete(@thumb_small_path) if File.exists?(@thumb_small_path)
115
- File.delete(@thumb_large_path) if File.exists?(@thumb_large_path)
116
- rebuild_model :styles => { :thumb_small => "50x50#", :thumb_large => "60x60#" }
130
+ File.delete(@thumb_small_path) if File.exist?(@thumb_small_path)
131
+ File.delete(@thumb_large_path) if File.exist?(@thumb_large_path)
132
+ rebuild_model styles: { thumb_small: "50x50#", thumb_large: "60x60#" }
117
133
  @dummy = Dummy.new
118
134
  @file = File.new(fixture_file("5k.png"), 'rb')
119
135
 
@@ -123,9 +139,9 @@ class IntegrationTest < Test::Unit::TestCase
123
139
  @dummy.avatar.post_processing = true
124
140
  end
125
141
 
126
- teardown { @file.close }
142
+ after { @file.close }
127
143
 
128
- should "allow us to create all thumbnails in one go" do
144
+ it "allows us to create all thumbnails in one go" do
129
145
  assert_file_not_exists(@thumb_small_path)
130
146
  assert_file_not_exists(@thumb_large_path)
131
147
 
@@ -135,7 +151,15 @@ class IntegrationTest < Test::Unit::TestCase
135
151
  assert_file_exists(@thumb_large_path)
136
152
  end
137
153
 
138
- should "allow us to selectively create each thumbnail" do
154
+ it "allows us to selectively create each thumbnail" do
155
+ skip <<-EXPLANATION
156
+ #reprocess! calls #assign which calls Paperclip.io_adapters.for
157
+ which creates the tempfile. #assign then calls #post_process_file which
158
+ calls MediaTypeSpoofDetectionValidator#validate_each which calls
159
+ Paperclip.io_adapters.for, which creates another tempfile. That first
160
+ tempfile is the one that leaks.
161
+ EXPLANATION
162
+
139
163
  assert_file_not_exists(@thumb_small_path)
140
164
  assert_file_not_exists(@thumb_large_path)
141
165
 
@@ -149,143 +173,89 @@ class IntegrationTest < Test::Unit::TestCase
149
173
  end
150
174
 
151
175
  context "A model that modifies its original" do
152
- setup do
153
- rebuild_model :styles => { :original => "2x2#" }
176
+ before do
177
+ rebuild_model styles: { original: "2x2#" }
154
178
  @dummy = Dummy.new
155
179
  @file = File.new(fixture_file("5k.png"), 'rb')
156
180
  @dummy.avatar = @file
157
181
  end
158
182
 
159
- should "report the file size of the processed file and not the original" do
183
+ it "reports the file size of the processed file and not the original" do
160
184
  assert_not_equal File.size(@file.path), @dummy.avatar.size
161
185
  end
162
186
 
163
- teardown { @file.close }
187
+ after do
188
+ @file.close
189
+ # save attachment instance to run after hooks (including tempfile cleanup)
190
+ @dummy.avatar.save
191
+ end
164
192
  end
165
193
 
166
194
  context "A model with attachments scoped under an id" do
167
- setup do
168
- rebuild_model :styles => { :large => "100x100",
169
- :medium => "50x50" },
170
- :path => ":rails_root/tmp/:id/:attachments/:style.:extension"
195
+ before do
196
+ rebuild_model styles: { large: "100x100",
197
+ medium: "50x50" },
198
+ path: ":rails_root/tmp/:id/:attachments/:style.:extension"
171
199
  @dummy = Dummy.new
172
200
  @file = File.new(fixture_file("5k.png"), 'rb')
173
201
  @dummy.avatar = @file
174
202
  end
175
203
 
176
- teardown { @file.close }
204
+ after { @file.close }
177
205
 
178
206
  context "when saved" do
179
- setup do
207
+ before do
180
208
  @dummy.save
181
209
  @saved_path = @dummy.avatar.path(:large)
182
210
  end
183
211
 
184
- should "have a large file in the right place" do
212
+ it "has a large file in the right place" do
185
213
  assert_file_exists(@dummy.avatar.path(:large))
186
214
  end
187
215
 
188
216
  context "and deleted" do
189
- setup do
217
+ before do
190
218
  @dummy.avatar.clear
191
219
  @dummy.save
192
220
  end
193
221
 
194
- should "not have a large file in the right place anymore" do
222
+ it "does not have a large file in the right place anymore" do
195
223
  assert_file_not_exists(@saved_path)
196
224
  end
197
225
 
198
- should "not have its next two parent directories" do
226
+ it "does not have its next two parent directories" do
199
227
  assert_file_not_exists(File.dirname(@saved_path))
200
228
  assert_file_not_exists(File.dirname(File.dirname(@saved_path)))
201
229
  end
230
+ end
202
231
 
203
- before_should "not die if an unexpected SystemCallError happens" do
232
+ context 'and deleted where the delete fails' do
233
+ it "does not die if an unexpected SystemCallError happens" do
204
234
  FileUtils.stubs(:rmdir).raises(Errno::EPIPE)
235
+ assert_nothing_raised do
236
+ @dummy.avatar.clear
237
+ @dummy.save
238
+ end
205
239
  end
206
240
  end
207
241
  end
208
242
  end
209
243
 
210
- context "A model with no convert_options setting" do
211
- setup do
212
- rebuild_model :styles => { :large => "300x300>",
213
- :medium => "100x100",
214
- :thumb => ["32x32#", :gif] },
215
- :default_style => :medium,
216
- :url => "/:attachment/:class/:style/:id/:basename.:extension",
217
- :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
218
- @dummy = Dummy.new
219
- end
220
-
221
- should "have its definition return nil when asked about convert_options" do
222
- assert ! Dummy.attachment_definitions[:avatar][:convert_options]
223
- end
224
-
225
- context "redefined to have convert_options setting" do
226
- setup do
227
- rebuild_model :styles => { :large => "300x300>",
228
- :medium => "100x100",
229
- :thumb => ["32x32#", :gif] },
230
- :convert_options => "-strip -depth 8",
231
- :default_style => :medium,
232
- :url => "/:attachment/:class/:style/:id/:basename.:extension",
233
- :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
234
- end
235
-
236
- should "have its definition return convert_options value when asked about convert_options" do
237
- assert_equal "-strip -depth 8", Dummy.attachment_definitions[:avatar][:convert_options]
238
- end
239
- end
240
- end
241
-
242
- context "A model with no source_file_options setting" do
243
- setup do
244
- rebuild_model :styles => { :large => "300x300>",
245
- :medium => "100x100",
246
- :thumb => ["32x32#", :gif] },
247
- :default_style => :medium,
248
- :url => "/:attachment/:class/:style/:id/:basename.:extension",
249
- :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
250
- @dummy = Dummy.new
251
- end
252
-
253
- should "have its definition return nil when asked about source_file_options" do
254
- assert ! Dummy.attachment_definitions[:avatar][:source_file_options]
255
- end
256
-
257
- context "redefined to have source_file_options setting" do
258
- setup do
259
- rebuild_model :styles => { :large => "300x300>",
260
- :medium => "100x100",
261
- :thumb => ["32x32#", :gif] },
262
- :source_file_options => "-density 400",
263
- :default_style => :medium,
264
- :url => "/:attachment/:class/:style/:id/:basename.:extension",
265
- :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
266
- end
267
-
268
- should "have its definition return source_file_options value when asked about source_file_options" do
269
- assert_equal "-density 400", Dummy.attachment_definitions[:avatar][:source_file_options]
270
- end
271
- end
272
- end
273
-
274
244
  [000,002,022].each do |umask|
275
245
  context "when the umask is #{umask}" do
276
- setup do
246
+ before do
277
247
  rebuild_model
278
248
  @dummy = Dummy.new
279
249
  @file = File.new(fixture_file("5k.png"), 'rb')
280
250
  @umask = File.umask(umask)
281
251
  end
282
252
 
283
- teardown do
253
+ after do
284
254
  File.umask @umask
285
255
  @file.close
286
256
  end
287
257
 
288
- should "respect the current umask" do
258
+ it "respects the current umask" do
289
259
  @dummy.avatar = @file
290
260
  @dummy.save
291
261
  assert_equal 0666&~umask, 0666&File.stat(@dummy.avatar.path).mode
@@ -295,17 +265,17 @@ class IntegrationTest < Test::Unit::TestCase
295
265
 
296
266
  [0666,0664,0640].each do |perms|
297
267
  context "when the perms are #{perms}" do
298
- setup do
299
- rebuild_model :override_file_permissions => perms
268
+ before do
269
+ rebuild_model override_file_permissions: perms
300
270
  @dummy = Dummy.new
301
271
  @file = File.new(fixture_file("5k.png"), 'rb')
302
272
  end
303
273
 
304
- teardown do
274
+ after do
305
275
  @file.close
306
276
  end
307
277
 
308
- should "respect the current perms" do
278
+ it "respects the current perms" do
309
279
  @dummy.avatar = @file
310
280
  @dummy.save
311
281
  assert_equal perms, File.stat(@dummy.avatar.path).mode & 0777
@@ -313,23 +283,23 @@ class IntegrationTest < Test::Unit::TestCase
313
283
  end
314
284
  end
315
285
 
316
- should "skip chmod operation, when override_file_permissions is set to false (e.g. useful when using CIFS mounts)" do
286
+ it "skips chmod operation, when override_file_permissions is set to false (e.g. useful when using CIFS mounts)" do
317
287
  FileUtils.expects(:chmod).never
318
288
 
319
- rebuild_model :override_file_permissions => false
289
+ rebuild_model override_file_permissions: false
320
290
  dummy = Dummy.create!
321
291
  dummy.avatar = @file
322
292
  dummy.save
323
293
  end
324
294
 
325
295
  context "A model with a filesystem attachment" do
326
- setup do
327
- rebuild_model :styles => { :large => "300x300>",
328
- :medium => "100x100",
329
- :thumb => ["32x32#", :gif] },
330
- :default_style => :medium,
331
- :url => "/:attachment/:class/:style/:id/:basename.:extension",
332
- :path => ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
296
+ before do
297
+ rebuild_model styles: { large: "300x300>",
298
+ medium: "100x100",
299
+ thumb: ["32x32#", :gif] },
300
+ default_style: :medium,
301
+ url: "/:attachment/:class/:style/:id/:basename.:extension",
302
+ path: ":rails_root/tmp/:attachment/:class/:style/:id/:basename.:extension"
333
303
  @dummy = Dummy.new
334
304
  @file = File.new(fixture_file("5k.png"), 'rb')
335
305
  @bad_file = File.new(fixture_file("bad.png"), 'rb')
@@ -339,9 +309,9 @@ class IntegrationTest < Test::Unit::TestCase
339
309
  assert @dummy.save
340
310
  end
341
311
 
342
- teardown { [@file, @bad_file].each(&:close) }
312
+ after { [@file, @bad_file].each(&:close) }
343
313
 
344
- should "write and delete its files" do
314
+ it "writes and delete its files" do
345
315
  [["434x66", :original],
346
316
  ["300x46", :large],
347
317
  ["100x15", :medium],
@@ -379,7 +349,7 @@ class IntegrationTest < Test::Unit::TestCase
379
349
  assert_nil @d2.avatar_file_name
380
350
  end
381
351
 
382
- should "work exactly the same when new as when reloaded" do
352
+ it "works exactly the same when new as when reloaded" do
383
353
  @d2 = Dummy.find(@dummy.id)
384
354
 
385
355
  assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
@@ -397,27 +367,34 @@ class IntegrationTest < Test::Unit::TestCase
397
367
  end
398
368
  end
399
369
 
400
- should "not abide things that don't have adapters" do
370
+ it "does not abide things that don't have adapters" do
401
371
  assert_raises(Paperclip::AdapterRegistry::NoHandlerError) do
402
372
  @dummy.avatar = "not a file"
403
373
  end
404
374
  end
405
375
 
406
- should "not be ok with bad files" do
376
+ it "is not ok with bad files" do
407
377
  @dummy.avatar = @bad_file
408
378
  assert ! @dummy.valid?
379
+ # save attachment instance to run after hooks (including tempfile cleanup)
380
+ @dummy.avatar.save
409
381
  end
410
382
 
411
- should "know the difference between good files, bad files, and not files when validating" do
383
+ it "knows the difference between good files, bad files, and not files when validating" do
412
384
  Dummy.validates_attachment_presence :avatar
413
385
  @d2 = Dummy.find(@dummy.id)
414
386
  @d2.avatar = @file
415
- assert @d2.valid?, @d2.errors.full_messages.inspect
387
+ assert @d2.valid?, @d2.errors.full_messages.inspect
388
+ # save attachment instance to run after hooks (including tempfile cleanup)
389
+ @d2.avatar.save
390
+
416
391
  @d2.avatar = @bad_file
417
392
  assert ! @d2.valid?
393
+ # save attachment instance to run after hooks (including tempfile cleanup)
394
+ @d2.avatar.save
418
395
  end
419
396
 
420
- should "be able to reload without saving and not have the file disappear" do
397
+ it "is able to reload without saving and not have the file disappear" do
421
398
  @dummy.avatar = @file
422
399
  assert @dummy.save, @dummy.errors.full_messages.inspect
423
400
  @dummy.avatar.clear
@@ -427,33 +404,33 @@ class IntegrationTest < Test::Unit::TestCase
427
404
  end
428
405
 
429
406
  context "that is assigned its file from another Paperclip attachment" do
430
- setup do
407
+ before do
431
408
  @dummy2 = Dummy.new
432
- @file2 = File.new(fixture_file("12k.png"), 'rb')
433
- assert @dummy2.avatar = @file2
409
+ @file2 = File.new(fixture_file("12k.png"), 'rb')
410
+ assert @dummy2.avatar = @file2
434
411
  @dummy2.save
435
412
  end
436
413
 
437
- teardown { @file2.close }
414
+ after { @file2.close }
438
415
 
439
- should "work when assigned a file" do
416
+ it "works when assigned a file" do
440
417
  assert_not_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
441
- `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
418
+ `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
442
419
 
443
420
  assert @dummy.avatar = @dummy2.avatar
444
421
  @dummy.save
445
422
  assert_equal @dummy.avatar_file_name, @dummy2.avatar_file_name
446
423
  assert_equal `identify -format "%wx%h" "#{@dummy.avatar.path(:original)}"`,
447
- `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
424
+ `identify -format "%wx%h" "#{@dummy2.avatar.path(:original)}"`
448
425
  end
449
426
  end
450
427
 
451
428
  end
452
429
 
453
430
  context "A model with an attachments association and a Paperclip attachment" do
454
- setup do
431
+ before do
455
432
  Dummy.class_eval do
456
- has_many :attachments, :class_name => 'Dummy'
433
+ has_many :attachments, class_name: 'Dummy'
457
434
  end
458
435
 
459
436
  @file = File.new(fixture_file("5k.png"), 'rb')
@@ -461,45 +438,45 @@ class IntegrationTest < Test::Unit::TestCase
461
438
  @dummy.avatar = @file
462
439
  end
463
440
 
464
- teardown { @file.close }
441
+ after { @file.close }
465
442
 
466
- should "should not error when saving" do
443
+ it "does not error when saving" do
467
444
  @dummy.save!
468
445
  end
469
446
  end
470
447
 
471
448
  context "A model with an attachment with hash in file name" do
472
- setup do
473
- @settings = { :styles => { :thumb => "50x50#" },
474
- :path => ":rails_root/public/system/:attachment/:id_partition/:style/:hash.:extension",
475
- :url => "/system/:attachment/:id_partition/:style/:hash.:extension",
476
- :hash_secret => "somesecret" }
449
+ before do
450
+ @settings = { styles: { thumb: "50x50#" },
451
+ path: ":rails_root/public/system/:attachment/:id_partition/:style/:hash.:extension",
452
+ url: "/system/:attachment/:id_partition/:style/:hash.:extension",
453
+ hash_secret: "somesecret" }
477
454
 
478
455
  rebuild_model @settings
479
456
 
480
457
  @file = File.new(fixture_file("5k.png"), 'rb')
481
- @dummy = Dummy.create! :avatar => @file
458
+ @dummy = Dummy.create! avatar: @file
482
459
  end
483
460
 
484
- teardown do
461
+ after do
485
462
  @file.close
486
463
  end
487
464
 
488
- should "be accessible" do
465
+ it "is accessible" do
489
466
  assert_file_exists(@dummy.avatar.path(:original))
490
467
  assert_file_exists(@dummy.avatar.path(:thumb))
491
468
  end
492
469
 
493
470
  context "when new style is added" do
494
- setup do
471
+ before do
495
472
  @dummy.avatar.options[:styles][:mini] = "25x25#"
496
473
  @dummy.avatar.instance_variable_set :@normalized_styles, nil
497
- Time.stubs(:now => Time.now + 10)
474
+ Time.stubs(now: Time.now + 10)
498
475
  @dummy.avatar.reprocess!
499
476
  @dummy.reload
500
477
  end
501
478
 
502
- should "make all the styles accessible" do
479
+ it "makes all the styles accessible" do
503
480
  assert_file_exists(@dummy.avatar.path(:original))
504
481
  assert_file_exists(@dummy.avatar.path(:thumb))
505
482
  assert_file_exists(@dummy.avatar.path(:mini))
@@ -529,22 +506,25 @@ class IntegrationTest < Test::Unit::TestCase
529
506
  end
530
507
 
531
508
  context "A model with an S3 attachment" do
532
- setup do
533
- rebuild_model :styles => { :large => "300x300>",
534
- :medium => "100x100",
535
- :thumb => ["32x32#", :gif],
536
- :custom => {
537
- :geometry => "32x32#",
538
- :s3_headers => { 'Cache-Control' => 'max-age=31557600' },
539
- :s3_metadata => { 'foo' => 'bar'}
540
- }
541
- },
542
- :storage => :s3,
543
- :s3_credentials => File.new(fixture_file('s3.yml')),
544
- :s3_options => { :logger => Paperclip.logger },
545
- :default_style => :medium,
546
- :bucket => ENV['S3_BUCKET'],
547
- :path => ":class/:attachment/:id/:style/:basename.:extension"
509
+ before do
510
+ rebuild_model(
511
+ styles: {
512
+ large: "300x300>",
513
+ medium: "100x100",
514
+ thumb: ["32x32#", :gif],
515
+ custom: {
516
+ geometry: "32x32#",
517
+ s3_headers: { 'Cache-Control' => 'max-age=31557600' },
518
+ s3_metadata: { 'foo' => 'bar'}
519
+ }
520
+ },
521
+ storage: :s3,
522
+ s3_credentials: File.new(fixture_file('s3.yml')),
523
+ s3_options: { logger: Paperclip.logger },
524
+ default_style: :medium,
525
+ bucket: ENV['S3_BUCKET'],
526
+ path: ":class/:attachment/:id/:style/:basename.:extension"
527
+ )
548
528
 
549
529
  @dummy = Dummy.new
550
530
  @file = File.new(fixture_file('5k.png'), 'rb')
@@ -557,29 +537,29 @@ class IntegrationTest < Test::Unit::TestCase
557
537
  @files_on_s3 = s3_files_for(@dummy.avatar)
558
538
  end
559
539
 
560
- teardown do
540
+ after do
561
541
  @file.close
562
542
  @bad_file.close
563
543
  @files_on_s3.values.each(&:close) if @files_on_s3
564
544
  end
565
545
 
566
546
  context 'assigning itself to a new model' do
567
- setup do
547
+ before do
568
548
  @d2 = Dummy.new
569
549
  @d2.avatar = @dummy.avatar
570
550
  @d2.save
571
551
  end
572
552
 
573
- should "have the same name as the old file" do
553
+ it "has the same name as the old file" do
574
554
  assert_equal @d2.avatar.original_filename, @dummy.avatar.original_filename
575
555
  end
576
556
  end
577
557
 
578
- should "have the same contents as the original" do
558
+ it "has the same contents as the original" do
579
559
  assert_equal @file.read, @files_on_s3[:original].read
580
560
  end
581
561
 
582
- should "write and delete its files" do
562
+ it "writes and delete its files" do
583
563
  [["434x66", :original],
584
564
  ["300x46", :large],
585
565
  ["100x15", :medium],
@@ -611,7 +591,7 @@ class IntegrationTest < Test::Unit::TestCase
611
591
  assert_nil @d2.avatar_file_name
612
592
  end
613
593
 
614
- should "work exactly the same when new as when reloaded" do
594
+ it "works exactly the same when new as when reloaded" do
615
595
  @d2 = Dummy.find(@dummy.id)
616
596
 
617
597
  assert_equal @dummy.avatar_file_name, @d2.avatar_file_name
@@ -635,7 +615,7 @@ class IntegrationTest < Test::Unit::TestCase
635
615
  end
636
616
  end
637
617
 
638
- should "know the difference between good files, bad files, and nil" do
618
+ it "knows the difference between good files, bad files, and nil" do
639
619
  @dummy.avatar = @bad_file
640
620
  assert ! @dummy.valid?
641
621
  @dummy.avatar = nil
@@ -651,7 +631,7 @@ class IntegrationTest < Test::Unit::TestCase
651
631
  assert ! @d2.valid?
652
632
  end
653
633
 
654
- should "be able to reload without saving and not have the file disappear" do
634
+ it "is able to reload without saving and not have the file disappear" do
655
635
  @dummy.avatar = @file
656
636
  assert @dummy.save
657
637
  @dummy.avatar = nil
@@ -660,28 +640,28 @@ class IntegrationTest < Test::Unit::TestCase
660
640
  assert_equal "5k.png", @dummy.avatar_file_name
661
641
  end
662
642
 
663
- should "have the right content type" do
643
+ it "has the right content type" do
664
644
  headers = s3_headers_for(@dummy.avatar, :original)
665
645
  assert_equal 'image/png', headers['content-type']
666
646
  end
667
647
 
668
- should "have the right style-specific headers" do
648
+ it "has the right style-specific headers" do
669
649
  headers = s3_headers_for(@dummy.avatar, :custom)
670
650
  assert_equal 'max-age=31557600', headers['cache-control']
671
651
  end
672
652
 
673
- should "have the right style-specific metadata" do
653
+ it "has the right style-specific metadata" do
674
654
  headers = s3_headers_for(@dummy.avatar, :custom)
675
655
  assert_equal 'bar', headers['x-amz-meta-foo']
676
656
  end
677
657
 
678
658
  context "with non-english character in the file name" do
679
- setup do
659
+ before do
680
660
  @file.stubs(:original_filename).returns("クリップ.png")
681
661
  @dummy.avatar = @file
682
662
  end
683
663
 
684
- should "not raise any error" do
664
+ it "does not raise any error" do
685
665
  @dummy.save!
686
666
  end
687
667
  end
@@ -689,14 +669,14 @@ class IntegrationTest < Test::Unit::TestCase
689
669
  end
690
670
 
691
671
  context "Copying attachments between models" do
692
- setup do
672
+ before do
693
673
  rebuild_model
694
674
  @file = File.new(fixture_file("5k.png"), 'rb')
695
675
  end
696
676
 
697
- teardown { @file.close }
677
+ after { @file.close }
698
678
 
699
- should "succeed when original attachment is a file" do
679
+ it "succeeds when original attachment is a file" do
700
680
  original = Dummy.new
701
681
  original.avatar = @file
702
682
  assert original.save
@@ -708,7 +688,7 @@ class IntegrationTest < Test::Unit::TestCase
708
688
  assert copy.avatar.present?
709
689
  end
710
690
 
711
- should "succeed when original attachment is empty" do
691
+ it "succeeds when original attachment is empty" do
712
692
  original = Dummy.create!
713
693
 
714
694
  copy = Dummy.new