kt-paperclip 6.2.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 (191) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +3 -0
  4. data/.gitignore +19 -0
  5. data/.hound.yml +1050 -0
  6. data/.rubocop.yml +1 -0
  7. data/.travis.yml +47 -0
  8. data/Appraisals +24 -0
  9. data/CONTRIBUTING.md +86 -0
  10. data/Gemfile +18 -0
  11. data/LICENSE +24 -0
  12. data/NEWS +515 -0
  13. data/README.md +1053 -0
  14. data/RELEASING.md +17 -0
  15. data/Rakefile +52 -0
  16. data/UPGRADING +17 -0
  17. data/features/basic_integration.feature +85 -0
  18. data/features/migration.feature +29 -0
  19. data/features/rake_tasks.feature +62 -0
  20. data/features/step_definitions/attachment_steps.rb +110 -0
  21. data/features/step_definitions/html_steps.rb +15 -0
  22. data/features/step_definitions/rails_steps.rb +257 -0
  23. data/features/step_definitions/s3_steps.rb +14 -0
  24. data/features/step_definitions/web_steps.rb +106 -0
  25. data/features/support/env.rb +12 -0
  26. data/features/support/fakeweb.rb +11 -0
  27. data/features/support/file_helpers.rb +34 -0
  28. data/features/support/fixtures/boot_config.txt +15 -0
  29. data/features/support/fixtures/gemfile.txt +5 -0
  30. data/features/support/fixtures/preinitializer.txt +20 -0
  31. data/features/support/paths.rb +28 -0
  32. data/features/support/rails.rb +39 -0
  33. data/features/support/selectors.rb +19 -0
  34. data/gemfiles/4.2.gemfile +20 -0
  35. data/gemfiles/5.0.gemfile +20 -0
  36. data/gemfiles/5.1.gemfile +20 -0
  37. data/gemfiles/5.2.gemfile +20 -0
  38. data/gemfiles/6.0.gemfile +20 -0
  39. data/lib/generators/paperclip/USAGE +8 -0
  40. data/lib/generators/paperclip/paperclip_generator.rb +36 -0
  41. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
  42. data/lib/paperclip.rb +215 -0
  43. data/lib/paperclip/attachment.rb +617 -0
  44. data/lib/paperclip/attachment_registry.rb +60 -0
  45. data/lib/paperclip/callbacks.rb +42 -0
  46. data/lib/paperclip/content_type_detector.rb +80 -0
  47. data/lib/paperclip/errors.rb +34 -0
  48. data/lib/paperclip/file_command_content_type_detector.rb +28 -0
  49. data/lib/paperclip/filename_cleaner.rb +15 -0
  50. data/lib/paperclip/geometry.rb +157 -0
  51. data/lib/paperclip/geometry_detector_factory.rb +45 -0
  52. data/lib/paperclip/geometry_parser_factory.rb +31 -0
  53. data/lib/paperclip/glue.rb +17 -0
  54. data/lib/paperclip/has_attached_file.rb +116 -0
  55. data/lib/paperclip/helpers.rb +60 -0
  56. data/lib/paperclip/interpolations.rb +201 -0
  57. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  58. data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
  59. data/lib/paperclip/io_adapters/attachment_adapter.rb +47 -0
  60. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  61. data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
  62. data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
  63. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
  64. data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
  65. data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
  66. data/lib/paperclip/io_adapters/registry.rb +36 -0
  67. data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
  68. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
  69. data/lib/paperclip/io_adapters/uri_adapter.rb +68 -0
  70. data/lib/paperclip/locales/en.yml +18 -0
  71. data/lib/paperclip/logger.rb +21 -0
  72. data/lib/paperclip/matchers.rb +64 -0
  73. data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
  74. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
  75. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
  76. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
  77. data/lib/paperclip/media_type_spoof_detector.rb +90 -0
  78. data/lib/paperclip/missing_attachment_styles.rb +84 -0
  79. data/lib/paperclip/processor.rb +56 -0
  80. data/lib/paperclip/processor_helpers.rb +52 -0
  81. data/lib/paperclip/rails_environment.rb +21 -0
  82. data/lib/paperclip/railtie.rb +31 -0
  83. data/lib/paperclip/schema.rb +81 -0
  84. data/lib/paperclip/storage.rb +3 -0
  85. data/lib/paperclip/storage/filesystem.rb +99 -0
  86. data/lib/paperclip/storage/fog.rb +252 -0
  87. data/lib/paperclip/storage/s3.rb +461 -0
  88. data/lib/paperclip/style.rb +106 -0
  89. data/lib/paperclip/tempfile.rb +42 -0
  90. data/lib/paperclip/tempfile_factory.rb +22 -0
  91. data/lib/paperclip/thumbnail.rb +131 -0
  92. data/lib/paperclip/url_generator.rb +76 -0
  93. data/lib/paperclip/validators.rb +73 -0
  94. data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
  95. data/lib/paperclip/validators/attachment_file_name_validator.rb +75 -0
  96. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
  97. data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
  98. data/lib/paperclip/validators/attachment_size_validator.rb +109 -0
  99. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
  100. data/lib/paperclip/version.rb +3 -0
  101. data/lib/tasks/paperclip.rake +140 -0
  102. data/paperclip.gemspec +50 -0
  103. data/shoulda_macros/paperclip.rb +134 -0
  104. data/spec/database.yml +4 -0
  105. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  106. data/spec/paperclip/attachment_processing_spec.rb +79 -0
  107. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  108. data/spec/paperclip/attachment_spec.rb +1590 -0
  109. data/spec/paperclip/content_type_detector_spec.rb +47 -0
  110. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  111. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  112. data/spec/paperclip/geometry_detector_spec.rb +38 -0
  113. data/spec/paperclip/geometry_parser_spec.rb +73 -0
  114. data/spec/paperclip/geometry_spec.rb +255 -0
  115. data/spec/paperclip/glue_spec.rb +42 -0
  116. data/spec/paperclip/has_attached_file_spec.rb +78 -0
  117. data/spec/paperclip/integration_spec.rb +702 -0
  118. data/spec/paperclip/interpolations_spec.rb +270 -0
  119. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  120. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +140 -0
  121. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
  122. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  123. data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
  124. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +137 -0
  125. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  126. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
  127. data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
  128. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  129. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  130. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +221 -0
  131. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  132. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
  133. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  134. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  135. data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
  136. data/spec/paperclip/meta_class_spec.rb +30 -0
  137. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
  138. data/spec/paperclip/paperclip_spec.rb +196 -0
  139. data/spec/paperclip/plural_cache_spec.rb +37 -0
  140. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  141. data/spec/paperclip/processor_spec.rb +26 -0
  142. data/spec/paperclip/rails_environment_spec.rb +30 -0
  143. data/spec/paperclip/rake_spec.rb +103 -0
  144. data/spec/paperclip/schema_spec.rb +252 -0
  145. data/spec/paperclip/storage/filesystem_spec.rb +79 -0
  146. data/spec/paperclip/storage/fog_spec.rb +560 -0
  147. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  148. data/spec/paperclip/storage/s3_spec.rb +1695 -0
  149. data/spec/paperclip/style_spec.rb +251 -0
  150. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  151. data/spec/paperclip/tempfile_spec.rb +35 -0
  152. data/spec/paperclip/thumbnail_spec.rb +504 -0
  153. data/spec/paperclip/url_generator_spec.rb +221 -0
  154. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  155. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +159 -0
  156. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
  157. data/spec/paperclip/validators/attachment_size_validator_spec.rb +235 -0
  158. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
  159. data/spec/paperclip/validators_spec.rb +164 -0
  160. data/spec/spec_helper.rb +45 -0
  161. data/spec/support/assertions.rb +84 -0
  162. data/spec/support/fake_model.rb +24 -0
  163. data/spec/support/fake_rails.rb +12 -0
  164. data/spec/support/fixtures/12k.png +0 -0
  165. data/spec/support/fixtures/50x50.png +0 -0
  166. data/spec/support/fixtures/5k.png +0 -0
  167. data/spec/support/fixtures/animated +0 -0
  168. data/spec/support/fixtures/animated.gif +0 -0
  169. data/spec/support/fixtures/animated.unknown +0 -0
  170. data/spec/support/fixtures/bad.png +1 -0
  171. data/spec/support/fixtures/empty.html +1 -0
  172. data/spec/support/fixtures/empty.xlsx +0 -0
  173. data/spec/support/fixtures/fog.yml +8 -0
  174. data/spec/support/fixtures/rotated.jpg +0 -0
  175. data/spec/support/fixtures/s3.yml +8 -0
  176. data/spec/support/fixtures/spaced file.jpg +0 -0
  177. data/spec/support/fixtures/spaced file.png +0 -0
  178. data/spec/support/fixtures/text.txt +1 -0
  179. data/spec/support/fixtures/twopage.pdf +0 -0
  180. data/spec/support/fixtures/uppercase.PNG +0 -0
  181. data/spec/support/matchers/accept.rb +5 -0
  182. data/spec/support/matchers/exist.rb +5 -0
  183. data/spec/support/matchers/have_column.rb +23 -0
  184. data/spec/support/mock_attachment.rb +24 -0
  185. data/spec/support/mock_interpolator.rb +24 -0
  186. data/spec/support/mock_url_generator_builder.rb +26 -0
  187. data/spec/support/model_reconstruction.rb +72 -0
  188. data/spec/support/reporting.rb +11 -0
  189. data/spec/support/test_data.rb +13 -0
  190. data/spec/support/version_helper.rb +9 -0
  191. metadata +586 -0
@@ -0,0 +1,270 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::Interpolations do
4
+ it "returns all methods but the infrastructure when sent #all" do
5
+ methods = Paperclip::Interpolations.all
6
+ assert !methods.include?(:[])
7
+ assert !methods.include?(:[]=)
8
+ assert !methods.include?(:all)
9
+ methods.each do |m|
10
+ assert Paperclip::Interpolations.respond_to?(m)
11
+ end
12
+ end
13
+
14
+ it "returns the Rails.root" do
15
+ assert_equal Rails.root, Paperclip::Interpolations.rails_root(:attachment, :style)
16
+ end
17
+
18
+ it "returns the Rails.env" do
19
+ assert_equal Rails.env, Paperclip::Interpolations.rails_env(:attachment, :style)
20
+ end
21
+
22
+ it "returns the class of the Interpolations module when called with no params" do
23
+ assert_equal Module, Paperclip::Interpolations.class
24
+ end
25
+
26
+ it "returns the class of the instance" do
27
+ class Thing; end
28
+ attachment = spy
29
+ expect(attachment).to receive(:instance).and_return(attachment)
30
+ expect(attachment).to receive(:class).and_return(Thing)
31
+ assert_equal "things", Paperclip::Interpolations.class(attachment, :style)
32
+ end
33
+
34
+ it "returns the basename of the file" do
35
+ attachment = spy
36
+ expect(attachment).to receive(:original_filename).and_return("one.jpg")
37
+ assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
38
+ end
39
+
40
+ it "returns the extension of the file" do
41
+ attachment = spy
42
+ expect(attachment).to receive(:original_filename).and_return("one.jpg")
43
+ expect(attachment).to receive(:styles).and_return({})
44
+ assert_equal "jpg", Paperclip::Interpolations.extension(attachment, :style)
45
+ end
46
+
47
+ it "returns the extension of the file as the format if defined in the style" do
48
+ attachment = spy
49
+ expect(attachment).to_not receive(:original_filename)
50
+ expect(attachment).to receive(:styles).at_least(2).times.and_return(style: { format: "png" })
51
+
52
+ [:style, "style"].each do |style|
53
+ assert_equal "png", Paperclip::Interpolations.extension(attachment, style)
54
+ end
55
+ end
56
+
57
+ it "returns the extension of the file based on the content type" do
58
+ attachment = spy
59
+ expect(attachment).to receive(:content_type).and_return("image/png")
60
+ expect(attachment).to receive(:styles).and_return({})
61
+ interpolations = Paperclip::Interpolations
62
+ expect(interpolations).to receive(:extension).and_return("random")
63
+ assert_equal "png", interpolations.content_type_extension(attachment, :style)
64
+ end
65
+
66
+ it "returns the original extension of the file if it matches a content type extension" do
67
+ attachment = spy
68
+ expect(attachment).to receive(:content_type).and_return("image/jpeg")
69
+ expect(attachment).to receive(:styles).and_return({})
70
+ interpolations = Paperclip::Interpolations
71
+ expect(interpolations).to receive(:extension).and_return("jpe")
72
+ assert_equal "jpe", interpolations.content_type_extension(attachment, :style)
73
+ end
74
+
75
+ it "returns the extension of the file with a dot" do
76
+ attachment = spy
77
+ expect(attachment).to receive(:original_filename).and_return("one.jpg")
78
+ expect(attachment).to receive(:styles).and_return({})
79
+ assert_equal ".jpg", Paperclip::Interpolations.dotextension(attachment, :style)
80
+ end
81
+
82
+ it "returns the extension of the file without a dot if the extension is empty" do
83
+ attachment = spy
84
+ expect(attachment).to receive(:original_filename).and_return("one")
85
+ expect(attachment).to receive(:styles).and_return({})
86
+ assert_equal "", Paperclip::Interpolations.dotextension(attachment, :style)
87
+ end
88
+
89
+ it "returns the latter half of the content type of the extension if no match found" do
90
+ attachment = spy
91
+ allow(attachment).to receive(:content_type).at_least(1).times.and_return("not/found")
92
+ allow(attachment).to receive(:styles).and_return({})
93
+ interpolations = Paperclip::Interpolations
94
+ expect(interpolations).to receive(:extension).and_return("random")
95
+ assert_equal "found", interpolations.content_type_extension(attachment, :style)
96
+ end
97
+
98
+ it "returns the format if defined in the style, ignoring the content type" do
99
+ attachment = spy
100
+ expect(attachment).to receive(:content_type).and_return("image/jpeg")
101
+ expect(attachment).to receive(:styles).and_return(style: { format: "png" })
102
+ interpolations = Paperclip::Interpolations
103
+ expect(interpolations).to receive(:extension).and_return("random")
104
+ assert_equal "png", interpolations.content_type_extension(attachment, :style)
105
+ end
106
+
107
+ it "is able to handle numeric style names" do
108
+ attachment = spy(
109
+ styles: {:"4" => {format: :expected_extension}}
110
+ )
111
+ assert_equal :expected_extension, Paperclip::Interpolations.extension(attachment, 4)
112
+ end
113
+
114
+ it "returns the #to_param of the attachment" do
115
+ attachment = spy
116
+ expect(attachment).to receive(:to_param).and_return("23-awesome")
117
+ expect(attachment).to receive(:instance).and_return(attachment)
118
+ assert_equal "23-awesome", Paperclip::Interpolations.param(attachment, :style)
119
+ end
120
+
121
+ it "returns the id of the attachment" do
122
+ attachment = spy
123
+ expect(attachment).to receive(:id).and_return(23)
124
+ expect(attachment).to receive(:instance).and_return(attachment)
125
+ assert_equal 23, Paperclip::Interpolations.id(attachment, :style)
126
+ end
127
+
128
+ it "returns nil for attachments to new records" do
129
+ attachment = spy
130
+ expect(attachment).to receive(:id).and_return(nil)
131
+ expect(attachment).to receive(:instance).and_return(attachment)
132
+ assert_nil Paperclip::Interpolations.id(attachment, :style)
133
+ end
134
+
135
+ it "returns the partitioned id of the attachment when the id is an integer" do
136
+ attachment = spy
137
+ expect(attachment).to receive(:id).and_return(23)
138
+ expect(attachment).to receive(:instance).and_return(attachment)
139
+ assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
140
+ end
141
+
142
+ it "returns the partitioned id when the id is above 999_999_999" do
143
+ attachment = spy
144
+ expect(attachment).to receive(:id).and_return(Paperclip::Interpolations::ID_PARTITION_LIMIT)
145
+ expect(attachment).to receive(:instance).and_return(attachment)
146
+ assert_equal "001/000/000/000",
147
+ Paperclip::Interpolations.id_partition(attachment, :style)
148
+ end
149
+
150
+ it "returns the partitioned id of the attachment when the id is a string" do
151
+ attachment = spy
152
+ expect(attachment).to receive(:id).and_return("32fnj23oio2f")
153
+ expect(attachment).to receive(:instance).and_return(attachment)
154
+ assert_equal "32f/nj2/3oi", Paperclip::Interpolations.id_partition(attachment, :style)
155
+ end
156
+
157
+ it "returns nil for the partitioned id of an attachment to a new record (when the id is nil)" do
158
+ attachment = spy
159
+ expect(attachment).to receive(:id).and_return(nil)
160
+ expect(attachment).to receive(:instance).and_return(attachment)
161
+ assert_nil Paperclip::Interpolations.id_partition(attachment, :style)
162
+ end
163
+
164
+ it "returns the name of the attachment" do
165
+ attachment = spy
166
+ expect(attachment).to receive(:name).and_return("file")
167
+ assert_equal "files", Paperclip::Interpolations.attachment(attachment, :style)
168
+ end
169
+
170
+ it "returns the style" do
171
+ assert_equal :style, Paperclip::Interpolations.style(:attachment, :style)
172
+ end
173
+
174
+ it "returns the default style" do
175
+ attachment = spy
176
+ expect(attachment).to receive(:default_style).and_return(:default_style)
177
+ assert_equal :default_style, Paperclip::Interpolations.style(attachment, nil)
178
+ end
179
+
180
+ it "reinterpolates :url" do
181
+ attachment = spy
182
+ expect(attachment).to receive(:url).with(:style, timestamp: false, escape: false).and_return("1234")
183
+ assert_equal "1234", Paperclip::Interpolations.url(attachment, :style)
184
+ end
185
+
186
+ it "raises if infinite loop detcted reinterpolating :url" do
187
+ attachment = Object.new
188
+ class << attachment
189
+ def url(*_args)
190
+ Paperclip::Interpolations.url(self, :style)
191
+ end
192
+ end
193
+ assert_raises(Paperclip::Errors::InfiniteInterpolationError) { Paperclip::Interpolations.url(attachment, :style) }
194
+ end
195
+
196
+ it "returns the filename as basename.extension" do
197
+ attachment = spy
198
+ expect(attachment).to receive(:styles).and_return({})
199
+ expect(attachment).to receive(:original_filename).and_return("one.jpg").twice
200
+ assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
201
+ end
202
+
203
+ it "returns the filename as basename.extension when format supplied" do
204
+ attachment = spy
205
+ expect(attachment).to receive(:styles).and_return(style: { format: :png })
206
+ expect(attachment).to receive(:original_filename).and_return("one.jpg").once
207
+ assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
208
+ end
209
+
210
+ it "returns the filename as basename when extension is blank" do
211
+ attachment = spy
212
+ allow(attachment).to receive(:styles).and_return({})
213
+ allow(attachment).to receive(:original_filename).and_return("one")
214
+ assert_equal "one", Paperclip::Interpolations.filename(attachment, :style)
215
+ end
216
+
217
+ it "returns the basename when the extension contains regexp special characters" do
218
+ attachment = spy
219
+ allow(attachment).to receive(:styles).and_return({})
220
+ allow(attachment).to receive(:original_filename).and_return("one.ab)")
221
+ assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
222
+ end
223
+
224
+ it "returns the timestamp" do
225
+ now = Time.now
226
+ zone = "UTC"
227
+ attachment = spy
228
+ expect(attachment).to receive(:instance_read).with(:updated_at).and_return(now)
229
+ expect(attachment).to receive(:time_zone).and_return(zone)
230
+ assert_equal now.in_time_zone(zone).to_s, Paperclip::Interpolations.timestamp(attachment, :style)
231
+ end
232
+
233
+ it "returns updated_at" do
234
+ attachment = spy
235
+ seconds_since_epoch = 1234567890
236
+ expect(attachment).to receive(:updated_at).and_return(seconds_since_epoch)
237
+ assert_equal seconds_since_epoch, Paperclip::Interpolations.updated_at(attachment, :style)
238
+ end
239
+
240
+ it "returns attachment's hash when passing both arguments" do
241
+ attachment = spy
242
+ fake_hash = "a_wicked_secure_hash"
243
+ expect(attachment).to receive(:hash_key).and_return(fake_hash)
244
+ assert_equal fake_hash, Paperclip::Interpolations.hash(attachment, :style)
245
+ end
246
+
247
+ it "returns Object#hash when passing no argument" do
248
+ attachment = spy
249
+ fake_hash = "a_wicked_secure_hash"
250
+ expect(attachment).to_not receive(:hash_key)
251
+ assert_not_equal fake_hash, Paperclip::Interpolations.hash
252
+ end
253
+
254
+ it "calls all expected interpolations with the given arguments" do
255
+ expect(Paperclip::Interpolations).to receive(:id).with(:attachment, :style).and_return(1234)
256
+ expect(Paperclip::Interpolations).to receive(:attachment).with(:attachment, :style).and_return("attachments")
257
+ expect(Paperclip::Interpolations).to_not receive(:notreal)
258
+ value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
259
+ assert_equal ":notreal/1234/attachments", value
260
+ end
261
+
262
+ it "handles question marks" do
263
+ Paperclip.interpolates :foo? do
264
+ "bar"
265
+ end
266
+ expect(Paperclip::Interpolations).to_not receive(:fool)
267
+ value = Paperclip::Interpolations.interpolate(":fo/:foo?")
268
+ assert_equal ":fo/bar", value
269
+ end
270
+ end
@@ -0,0 +1,160 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::AbstractAdapter do
4
+ class TestAdapter < Paperclip::AbstractAdapter
5
+ attr_accessor :tempfile
6
+
7
+ def content_type
8
+ Paperclip::ContentTypeDetector.new(path).detect
9
+ end
10
+ end
11
+
12
+ subject { TestAdapter.new(nil) }
13
+
14
+ context "content type from file contents" do
15
+ before do
16
+ allow(subject).to receive(:path).and_return("image.png")
17
+ allow(Paperclip).to receive(:run).and_return("image/png\n")
18
+ allow_any_instance_of(Paperclip::ContentTypeDetector).to receive(:type_from_mime_magic).and_return("image/png")
19
+ end
20
+
21
+ it "returns the content type without newline" do
22
+ assert_equal "image/png", subject.content_type
23
+ end
24
+ end
25
+
26
+ context "nil?" do
27
+ it "returns false" do
28
+ assert !subject.nil?
29
+ end
30
+ end
31
+
32
+ context "delegation" do
33
+ before do
34
+ subject.tempfile = double("Tempfile")
35
+ end
36
+
37
+ [:binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink].each do |method|
38
+ it "delegates #{method} to @tempfile" do
39
+ allow(subject.tempfile).to receive(method)
40
+ subject.public_send(method)
41
+ expect(subject.tempfile).to have_received(method)
42
+ end
43
+ end
44
+ end
45
+
46
+ it "gets rid of slashes and colons in filenames" do
47
+ subject.original_filename = "awesome/file:name.png"
48
+
49
+ assert_equal "awesome_file_name.png", subject.original_filename
50
+ end
51
+
52
+ it "is an assignment" do
53
+ assert subject.assignment?
54
+ end
55
+
56
+ it "is not nil" do
57
+ assert !subject.nil?
58
+ end
59
+
60
+ it "generates a destination filename with no original filename" do
61
+ expect(subject.send(:destination).path).to_not be_nil
62
+ end
63
+
64
+ it "uses the original filename to generate the tempfile" do
65
+ subject.original_filename = "file.png"
66
+ expect(subject.send(:destination).path).to end_with(".png")
67
+ end
68
+
69
+ context "generates a fingerprint" do
70
+ subject { TestAdapter.new(nil, options) }
71
+
72
+ before do
73
+ allow(subject).to receive(:path).and_return(fixture_file("50x50.png"))
74
+ end
75
+
76
+ context "MD5" do
77
+ let(:options) { { hash_digest: Digest::MD5 } }
78
+
79
+ it "returns a fingerprint" do
80
+ expect(subject.fingerprint).to be_a String
81
+ expect(subject.fingerprint).to eq "a790b00c9b5d58a8fd17a1ec5a187129"
82
+ end
83
+ end
84
+
85
+ context "SHA256" do
86
+ let(:options) { { hash_digest: Digest::SHA256 } }
87
+
88
+ it "returns a fingerprint" do
89
+ expect(subject.fingerprint).to be_a String
90
+ expect(subject.fingerprint).
91
+ to eq "243d7ce1099719df25f600f1c369c629fb979f88d5a01dbe7d0d48c8e6715bb1"
92
+ end
93
+ end
94
+ end
95
+
96
+ context "#copy_to_tempfile" do
97
+ around do |example|
98
+ FileUtils.module_eval do
99
+ class << self
100
+ alias paperclip_ln ln
101
+
102
+ def ln(*)
103
+ raise Errno::EXDEV
104
+ end
105
+ end
106
+ end
107
+
108
+ example.run
109
+
110
+ FileUtils.module_eval do
111
+ class << self
112
+ alias ln paperclip_ln
113
+ undef paperclip_ln
114
+ end
115
+ end
116
+ end
117
+
118
+ it "should return a readable file even when linking fails" do
119
+ src = open(fixture_file("5k.png"), "rb")
120
+ expect(subject.send(:copy_to_tempfile, src).read).to eq src.read
121
+ end
122
+ end
123
+
124
+ context "#original_filename=" do
125
+ it "should not fail with a nil original filename" do
126
+ expect { subject.original_filename = nil }.not_to raise_error
127
+ end
128
+ end
129
+
130
+ context "#link_or_copy_file" do
131
+ class TestLinkOrCopyAdapter < Paperclip::AbstractAdapter
132
+ public :copy_to_tempfile, :destination
133
+ end
134
+
135
+ subject { TestLinkOrCopyAdapter.new(nil) }
136
+ let(:body) { "body" }
137
+
138
+ let(:file) do
139
+ t = Tempfile.new("destination")
140
+ t.print(body)
141
+ t.rewind
142
+ t
143
+ end
144
+
145
+ after do
146
+ file.close
147
+ file.unlink
148
+ end
149
+
150
+ it "should be able to read the file" do
151
+ expect(subject.copy_to_tempfile(file).read).to eq(body)
152
+ end
153
+
154
+ it "should be able to reopen the file after symlink has failed" do
155
+ expect(FileUtils).to receive(:ln).and_raise(Errno::EXDEV)
156
+
157
+ expect(subject.copy_to_tempfile(file).read).to eq(body)
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,140 @@
1
+ require "spec_helper"
2
+
3
+ describe Paperclip::AttachmentAdapter do
4
+ before do
5
+ rebuild_model path: "tmp/:class/:attachment/:style/:filename", styles: { thumb: "50x50" }
6
+ @attachment = Dummy.new.avatar
7
+ end
8
+
9
+ context "for an attachment" do
10
+ before do
11
+ @file = File.new(fixture_file("5k.png"))
12
+ @file.binmode
13
+
14
+ @attachment.assign(@file)
15
+ @attachment.save
16
+ @subject = Paperclip.io_adapters.for(@attachment,
17
+ hash_digest: Digest::MD5)
18
+ end
19
+
20
+ after do
21
+ @file.close
22
+ @subject.close
23
+ end
24
+
25
+ it "gets the right filename" do
26
+ assert_equal "5k.png", @subject.original_filename
27
+ end
28
+
29
+ it "forces binmode on tempfile" do
30
+ assert @subject.instance_variable_get("@tempfile").binmode?
31
+ end
32
+
33
+ it "gets the content type" do
34
+ assert_equal "image/png", @subject.content_type
35
+ end
36
+
37
+ it "gets the file's size" do
38
+ assert_equal 4456, @subject.size
39
+ end
40
+
41
+ it "returns false for a call to nil?" do
42
+ assert !@subject.nil?
43
+ end
44
+
45
+ it "generates a MD5 hash of the contents" do
46
+ expected = Digest::MD5.file(@file.path).to_s
47
+ assert_equal expected, @subject.fingerprint
48
+ end
49
+
50
+ it "reads the contents of the file" do
51
+ expected = @file.read
52
+ actual = @subject.read
53
+ assert !expected.empty?
54
+ assert_equal expected.length, actual.length
55
+ assert_equal expected, actual
56
+ end
57
+ end
58
+
59
+ context "for a file with restricted characters in the name" do
60
+ before do
61
+ file_contents = IO.read(fixture_file("animated.gif"))
62
+ @file = StringIO.new(file_contents)
63
+ allow(@file).to receive(:original_filename).and_return("image:restricted.gif")
64
+ @file.binmode
65
+
66
+ @attachment.assign(@file)
67
+ @attachment.save
68
+ @subject = Paperclip.io_adapters.for(@attachment,
69
+ hash_digest: Digest::MD5)
70
+ end
71
+
72
+ after do
73
+ @subject.close
74
+ end
75
+
76
+ it "does not generate paths that include restricted characters" do
77
+ expect(@subject.path).to_not match(/:/)
78
+ end
79
+
80
+ it "does not generate filenames that include restricted characters" do
81
+ assert_equal "image_restricted.gif", @subject.original_filename
82
+ end
83
+ end
84
+
85
+ context "for a style" do
86
+ before do
87
+ @file = File.new(fixture_file("5k.png"))
88
+ @file.binmode
89
+
90
+ @attachment.assign(@file)
91
+
92
+ @thumb = Tempfile.new("thumbnail").tap(&:binmode)
93
+ FileUtils.cp @attachment.queued_for_write[:thumb].path, @thumb.path
94
+
95
+ @attachment.save
96
+ @subject = Paperclip.io_adapters.for(@attachment.styles[:thumb],
97
+ hash_digest: Digest::MD5)
98
+ end
99
+
100
+ after do
101
+ @file.close
102
+ @thumb.close
103
+ @subject.close
104
+ end
105
+
106
+ it "gets the original filename" do
107
+ assert_equal "5k.png", @subject.original_filename
108
+ end
109
+
110
+ it "forces binmode on tempfile" do
111
+ assert @subject.instance_variable_get("@tempfile").binmode?
112
+ end
113
+
114
+ it "gets the content type" do
115
+ assert_equal "image/png", @subject.content_type
116
+ end
117
+
118
+ it "gets the thumbnail's file size" do
119
+ assert_equal @thumb.size, @subject.size
120
+ end
121
+
122
+ it "returns false for a call to nil?" do
123
+ assert !@subject.nil?
124
+ end
125
+
126
+ it "generates a MD5 hash of the contents" do
127
+ expected = Digest::MD5.file(@thumb.path).to_s
128
+ assert_equal expected, @subject.fingerprint
129
+ end
130
+
131
+ it "reads the contents of the thumbnail" do
132
+ @thumb.rewind
133
+ expected = @thumb.read
134
+ actual = @subject.read
135
+ assert !expected.empty?
136
+ assert_equal expected.length, actual.length
137
+ assert_equal expected, actual
138
+ end
139
+ end
140
+ end