paperclip 3.5.4 → 4.3.7

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

Potentially problematic release.


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

Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -6
  3. data/.hound.yml +1066 -0
  4. data/.rubocop.yml +1 -0
  5. data/.travis.yml +11 -17
  6. data/Appraisals +6 -14
  7. data/CONTRIBUTING.md +13 -8
  8. data/Gemfile +16 -3
  9. data/LICENSE +1 -3
  10. data/NEWS +167 -49
  11. data/README.md +294 -75
  12. data/RELEASING.md +17 -0
  13. data/Rakefile +6 -8
  14. data/features/basic_integration.feature +24 -6
  15. data/features/step_definitions/attachment_steps.rb +30 -22
  16. data/features/step_definitions/html_steps.rb +2 -2
  17. data/features/step_definitions/rails_steps.rb +44 -14
  18. data/features/step_definitions/web_steps.rb +1 -103
  19. data/features/support/env.rb +2 -2
  20. data/features/support/file_helpers.rb +2 -2
  21. data/features/support/fixtures/gemfile.txt +1 -1
  22. data/features/support/rails.rb +2 -1
  23. data/gemfiles/3.2.gemfile +14 -6
  24. data/gemfiles/4.1.gemfile +19 -0
  25. data/gemfiles/4.2.gemfile +19 -0
  26. data/lib/generators/paperclip/paperclip_generator.rb +0 -2
  27. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
  28. data/lib/paperclip/attachment.rb +132 -38
  29. data/lib/paperclip/attachment_registry.rb +1 -1
  30. data/lib/paperclip/callbacks.rb +11 -1
  31. data/lib/paperclip/content_type_detector.rb +25 -22
  32. data/lib/paperclip/deprecations.rb +42 -0
  33. data/lib/paperclip/errors.rb +5 -0
  34. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  35. data/lib/paperclip/geometry_detector_factory.rb +3 -1
  36. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  37. data/lib/paperclip/has_attached_file.rb +10 -0
  38. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  39. data/lib/paperclip/interpolations.rb +25 -12
  40. data/lib/paperclip/io_adapters/abstract_adapter.rb +3 -1
  41. data/lib/paperclip/io_adapters/attachment_adapter.rb +4 -4
  42. data/lib/paperclip/io_adapters/data_uri_adapter.rb +5 -10
  43. data/lib/paperclip/io_adapters/stringio_adapter.rb +6 -10
  44. data/lib/paperclip/io_adapters/uri_adapter.rb +30 -11
  45. data/lib/paperclip/locales/de.yml +18 -0
  46. data/lib/paperclip/locales/en.yml +1 -0
  47. data/lib/paperclip/locales/es.yml +18 -0
  48. data/lib/paperclip/locales/ja.yml +18 -0
  49. data/lib/paperclip/locales/pt-BR.yml +18 -0
  50. data/lib/paperclip/locales/zh-CN.yml +18 -0
  51. data/lib/paperclip/locales/zh-HK.yml +18 -0
  52. data/lib/paperclip/locales/zh-TW.yml +18 -0
  53. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
  54. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
  55. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  56. data/lib/paperclip/media_type_spoof_detector.rb +89 -0
  57. data/lib/paperclip/processor.rb +0 -37
  58. data/lib/paperclip/processor_helpers.rb +50 -0
  59. data/lib/paperclip/rails_environment.rb +25 -0
  60. data/lib/paperclip/schema.rb +10 -2
  61. data/lib/paperclip/storage/filesystem.rb +1 -1
  62. data/lib/paperclip/storage/fog.rb +18 -7
  63. data/lib/paperclip/storage/s3.rb +53 -22
  64. data/lib/paperclip/style.rb +8 -2
  65. data/lib/paperclip/tempfile_factory.rb +5 -1
  66. data/lib/paperclip/thumbnail.rb +12 -10
  67. data/lib/paperclip/url_generator.rb +11 -3
  68. data/lib/paperclip/validators/attachment_content_type_validator.rb +4 -0
  69. data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
  70. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
  71. data/lib/paperclip/validators/attachment_presence_validator.rb +4 -0
  72. data/lib/paperclip/validators/attachment_size_validator.rb +11 -3
  73. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +27 -0
  74. data/lib/paperclip/validators.rb +10 -3
  75. data/lib/paperclip/version.rb +1 -1
  76. data/lib/paperclip.rb +26 -8
  77. data/lib/tasks/paperclip.rake +17 -2
  78. data/paperclip.gemspec +16 -14
  79. data/shoulda_macros/paperclip.rb +0 -1
  80. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  81. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +20 -21
  82. data/spec/paperclip/attachment_registry_spec.rb +130 -0
  83. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +438 -397
  84. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +16 -19
  85. data/spec/paperclip/deprecations_spec.rb +65 -0
  86. data/{test/file_command_content_type_detector_test.rb → spec/paperclip/file_command_content_type_detector_spec.rb} +5 -6
  87. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  88. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  89. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  90. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +50 -52
  91. data/spec/paperclip/glue_spec.rb +44 -0
  92. data/{test/has_attached_file_test.rb → spec/paperclip/has_attached_file_spec.rb} +45 -28
  93. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +134 -126
  94. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +70 -46
  95. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +78 -0
  96. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +27 -29
  97. data/{test/io_adapters/data_uri_adapter_test.rb → spec/paperclip/io_adapters/data_uri_adapter_spec.rb} +26 -17
  98. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  99. data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +36 -40
  100. data/{test/io_adapters/http_url_proxy_adapter_test.rb → spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb} +31 -29
  101. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  102. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  103. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +10 -7
  104. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +20 -17
  105. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +41 -41
  106. data/{test/io_adapters/uri_adapter_test.rb → spec/paperclip/io_adapters/uri_adapter_spec.rb} +53 -28
  107. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  108. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +99 -0
  109. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  110. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  111. data/spec/paperclip/media_type_spoof_detector_spec.rb +79 -0
  112. data/spec/paperclip/meta_class_spec.rb +30 -0
  113. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  114. data/{test/paperclip_test.rb → spec/paperclip/paperclip_spec.rb} +53 -48
  115. data/spec/paperclip/plural_cache_spec.rb +37 -0
  116. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  117. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +5 -5
  118. data/spec/paperclip/rails_environment_spec.rb +33 -0
  119. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  120. data/spec/paperclip/schema_spec.rb +248 -0
  121. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  122. data/spec/paperclip/storage/fog_spec.rb +535 -0
  123. data/spec/paperclip/storage/s3_live_spec.rb +182 -0
  124. data/spec/paperclip/storage/s3_spec.rb +1526 -0
  125. data/spec/paperclip/style_spec.rb +255 -0
  126. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  127. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +123 -107
  128. data/spec/paperclip/url_generator_spec.rb +211 -0
  129. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  130. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  131. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +20 -20
  132. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +65 -58
  133. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  134. data/spec/paperclip/validators_spec.rb +164 -0
  135. data/spec/spec_helper.rb +43 -0
  136. data/spec/support/assertions.rb +71 -0
  137. data/spec/support/deprecations.rb +9 -0
  138. data/spec/support/fake_model.rb +25 -0
  139. data/spec/support/fake_rails.rb +12 -0
  140. data/spec/support/fixtures/empty.html +1 -0
  141. data/spec/support/fixtures/empty.xlsx +0 -0
  142. data/spec/support/fixtures/spaced file.jpg +0 -0
  143. data/spec/support/matchers/accept.rb +5 -0
  144. data/spec/support/matchers/exist.rb +5 -0
  145. data/spec/support/matchers/have_column.rb +23 -0
  146. data/spec/support/model_reconstruction.rb +60 -0
  147. data/spec/support/rails_helpers.rb +7 -0
  148. data/spec/support/test_data.rb +13 -0
  149. data/spec/support/version_helper.rb +9 -0
  150. metadata +334 -219
  151. data/RUNNING_TESTS.md +0 -4
  152. data/gemfiles/3.0.gemfile +0 -11
  153. data/gemfiles/3.1.gemfile +0 -11
  154. data/gemfiles/4.0.gemfile +0 -11
  155. data/test/attachment_definitions_test.rb +0 -12
  156. data/test/attachment_registry_test.rb +0 -88
  157. data/test/filename_cleaner_test.rb +0 -14
  158. data/test/generator_test.rb +0 -84
  159. data/test/geometry_detector_test.rb +0 -24
  160. data/test/helper.rb +0 -232
  161. data/test/io_adapters/abstract_adapter_test.rb +0 -58
  162. data/test/io_adapters/empty_string_adapter_test.rb +0 -18
  163. data/test/io_adapters/identity_adapter_test.rb +0 -8
  164. data/test/matchers/have_attached_file_matcher_test.rb +0 -24
  165. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -110
  166. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -69
  167. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -86
  168. data/test/meta_class_test.rb +0 -32
  169. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  170. data/test/plural_cache_test.rb +0 -36
  171. data/test/schema_test.rb +0 -200
  172. data/test/storage/fog_test.rb +0 -473
  173. data/test/storage/s3_live_test.rb +0 -179
  174. data/test/storage/s3_test.rb +0 -1356
  175. data/test/style_test.rb +0 -213
  176. data/test/support/mock_model.rb +0 -2
  177. data/test/tempfile_factory_test.rb +0 -17
  178. data/test/url_generator_test.rb +0 -187
  179. data/test/validators/attachment_content_type_validator_test.rb +0 -324
  180. data/test/validators_test.rb +0 -61
  181. /data/{test → spec}/database.yml +0 -0
  182. /data/{test → spec/support}/fixtures/12k.png +0 -0
  183. /data/{test → spec/support}/fixtures/50x50.png +0 -0
  184. /data/{test → spec/support}/fixtures/5k.png +0 -0
  185. /data/{test → spec/support}/fixtures/animated +0 -0
  186. /data/{test → spec/support}/fixtures/animated.gif +0 -0
  187. /data/{test → spec/support}/fixtures/animated.unknown +0 -0
  188. /data/{test → spec/support}/fixtures/bad.png +0 -0
  189. /data/{test → spec/support}/fixtures/fog.yml +0 -0
  190. /data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  191. /data/{test → spec/support}/fixtures/s3.yml +0 -0
  192. /data/{test → spec/support}/fixtures/spaced file.png +0 -0
  193. /data/{test → spec/support}/fixtures/text.txt +0 -0
  194. /data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  195. /data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  196. /data/{test → spec}/support/mock_attachment.rb +0 -0
  197. /data/{test → spec}/support/mock_interpolator.rb +0 -0
  198. /data/{test → spec}/support/mock_url_generator_builder.rb +0 -0
@@ -0,0 +1,535 @@
1
+ require 'spec_helper'
2
+ require 'fog/aws'
3
+ require 'fog/local'
4
+ require 'timecop'
5
+
6
+ describe Paperclip::Storage::Fog do
7
+ context "" do
8
+ before { Fog.mock! }
9
+
10
+ context "with credentials provided in a path string" do
11
+ before do
12
+ rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
13
+ storage: :fog,
14
+ url: '/:attachment/:filename',
15
+ fog_directory: "paperclip",
16
+ fog_credentials: fixture_file('fog.yml')
17
+ @file = File.new(fixture_file('5k.png'), 'rb')
18
+ @dummy = Dummy.new
19
+ @dummy.avatar = @file
20
+ end
21
+
22
+ after { @file.close }
23
+
24
+ it "has the proper information loading credentials from a file" do
25
+ assert_equal @dummy.avatar.fog_credentials[:provider], 'AWS'
26
+ end
27
+ end
28
+
29
+ context "with credentials provided in a File object" do
30
+ before do
31
+ rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
32
+ storage: :fog,
33
+ url: '/:attachment/:filename',
34
+ fog_directory: "paperclip",
35
+ fog_credentials: File.open(fixture_file('fog.yml'))
36
+ @file = File.new(fixture_file('5k.png'), 'rb')
37
+ @dummy = Dummy.new
38
+ @dummy.avatar = @file
39
+ end
40
+
41
+ after { @file.close }
42
+
43
+ it "has the proper information loading credentials from a file" do
44
+ assert_equal @dummy.avatar.fog_credentials[:provider], 'AWS'
45
+ end
46
+ end
47
+
48
+ context "with default values for path and url" do
49
+ before do
50
+ rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
51
+ storage: :fog,
52
+ url: '/:attachment/:filename',
53
+ fog_directory: "paperclip",
54
+ fog_credentials: {
55
+ provider: 'AWS',
56
+ aws_access_key_id: 'AWS_ID',
57
+ aws_secret_access_key: 'AWS_SECRET'
58
+ }
59
+ @file = File.new(fixture_file('5k.png'), 'rb')
60
+ @dummy = Dummy.new
61
+ @dummy.avatar = @file
62
+ end
63
+
64
+ after { @file.close }
65
+
66
+ it "is able to interpolate the path without blowing up" do
67
+ assert_equal File.expand_path(File.join(File.dirname(__FILE__), "../../../tmp/public/avatars/5k.png")),
68
+ @dummy.avatar.path
69
+ end
70
+ end
71
+
72
+ context "with no path or url given and using defaults" do
73
+ before do
74
+ rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
75
+ storage: :fog,
76
+ fog_directory: "paperclip",
77
+ fog_credentials: {
78
+ provider: 'AWS',
79
+ aws_access_key_id: 'AWS_ID',
80
+ aws_secret_access_key: 'AWS_SECRET'
81
+ }
82
+ @file = File.new(fixture_file('5k.png'), 'rb')
83
+ @dummy = Dummy.new
84
+ @dummy.id = 1
85
+ @dummy.avatar = @file
86
+ end
87
+
88
+ after { @file.close }
89
+
90
+ it "has correct path and url from interpolated defaults" do
91
+ assert_equal "dummies/avatars/000/000/001/original/5k.png", @dummy.avatar.path
92
+ end
93
+ end
94
+
95
+ context "with file params provided as lambda" do
96
+ before do
97
+ fog_file = lambda{ |a| { custom_header: a.instance.custom_method }}
98
+ klass = rebuild_model storage: :fog,
99
+ fog_file: fog_file
100
+
101
+ klass.class_eval do
102
+ def custom_method
103
+ 'foobar'
104
+ end
105
+ end
106
+
107
+
108
+ @dummy = Dummy.new
109
+ end
110
+
111
+ it "is able to evaluate correct values for file headers" do
112
+ assert_equal @dummy.avatar.send(:fog_file), { custom_header: 'foobar' }
113
+ end
114
+ end
115
+
116
+ before do
117
+ @fog_directory = 'papercliptests'
118
+
119
+ @credentials = {
120
+ provider: 'AWS',
121
+ aws_access_key_id: 'ID',
122
+ aws_secret_access_key: 'SECRET'
123
+ }
124
+
125
+ @connection = Fog::Storage.new(@credentials)
126
+ @connection.directories.create(
127
+ key: @fog_directory
128
+ )
129
+
130
+ @options = {
131
+ fog_directory: @fog_directory,
132
+ fog_credentials: @credentials,
133
+ fog_host: nil,
134
+ fog_file: {cache_control: 1234},
135
+ path: ":attachment/:basename:dotextension",
136
+ storage: :fog
137
+ }
138
+
139
+ rebuild_model(@options)
140
+ end
141
+
142
+ it "is extended by the Fog module" do
143
+ assert Dummy.new.avatar.is_a?(Paperclip::Storage::Fog)
144
+ end
145
+
146
+ context "when assigned" do
147
+ before do
148
+ @file = File.new(fixture_file('5k.png'), 'rb')
149
+ @dummy = Dummy.new
150
+ @dummy.avatar = @file
151
+ end
152
+
153
+ after do
154
+ @file.close
155
+ directory = @connection.directories.new(key: @fog_directory)
156
+ directory.files.each {|file| file.destroy}
157
+ directory.destroy
158
+ end
159
+
160
+ it "is rewound after flush_writes" do
161
+ @dummy.avatar.instance_eval "def after_flush_writes; end"
162
+
163
+ files = @dummy.avatar.queued_for_write.values
164
+ @dummy.save
165
+ assert files.none?(&:eof?), "Expect all the files to be rewinded."
166
+ end
167
+
168
+ it "is removed after after_flush_writes" do
169
+ paths = @dummy.avatar.queued_for_write.values.map(&:path)
170
+ @dummy.save
171
+ assert paths.none?{ |path| File.exist?(path) },
172
+ "Expect all the files to be deleted."
173
+ end
174
+
175
+ it 'is able to be copied to a local file' do
176
+ @dummy.save
177
+ tempfile = Tempfile.new("known_location")
178
+ tempfile.binmode
179
+ @dummy.avatar.copy_to_local_file(:original, tempfile.path)
180
+ tempfile.rewind
181
+ assert_equal @connection.directories.get(@fog_directory).files.get(@dummy.avatar.path).body,
182
+ tempfile.read
183
+ tempfile.close
184
+ end
185
+
186
+ it "passes the content type to the Fog::Storage::AWS::Files instance" do
187
+ Fog::Storage::AWS::Files.any_instance.expects(:create).with do |hash|
188
+ hash[:content_type]
189
+ end
190
+ @dummy.save
191
+ end
192
+
193
+ context "without a bucket" do
194
+ before do
195
+ @connection.directories.get(@fog_directory).destroy
196
+ end
197
+
198
+ it "creates the bucket" do
199
+ assert @dummy.save
200
+ assert @connection.directories.get(@fog_directory)
201
+ end
202
+ end
203
+
204
+ context "with a bucket" do
205
+ it "succeeds" do
206
+ assert @dummy.save
207
+ end
208
+ end
209
+
210
+ context "without a fog_host" do
211
+ before do
212
+ rebuild_model(@options.merge(fog_host: nil))
213
+ @dummy = Dummy.new
214
+ @dummy.avatar = StringIO.new('.')
215
+ @dummy.save
216
+ end
217
+
218
+ it "provides a public url" do
219
+ assert !@dummy.avatar.url.nil?
220
+ end
221
+ end
222
+
223
+ context "with a fog_host" do
224
+ before do
225
+ rebuild_model(@options.merge(fog_host: 'http://example.com'))
226
+ @dummy = Dummy.new
227
+ @dummy.avatar = StringIO.new(".\n")
228
+ @dummy.save
229
+ end
230
+
231
+ it "provides a public url" do
232
+ expect(@dummy.avatar.url).to match(/^http:\/\/example\.com\/avatars\/data\?\d*$/)
233
+ end
234
+ end
235
+
236
+ context "with a fog_host that includes a wildcard placeholder" do
237
+ before do
238
+ rebuild_model(
239
+ fog_directory: @fog_directory,
240
+ fog_credentials: @credentials,
241
+ fog_host: 'http://img%d.example.com',
242
+ path: ":attachment/:basename:dotextension",
243
+ storage: :fog
244
+ )
245
+ @dummy = Dummy.new
246
+ @dummy.avatar = StringIO.new(".\n")
247
+ @dummy.save
248
+ end
249
+
250
+ it "provides a public url" do
251
+ expect(@dummy.avatar.url).to match(/^http:\/\/img[0123]\.example\.com\/avatars\/data\?\d*$/)
252
+ end
253
+ end
254
+
255
+ context "with fog_public set to false" do
256
+ before do
257
+ rebuild_model(@options.merge(fog_public: false))
258
+ @dummy = Dummy.new
259
+ @dummy.avatar = StringIO.new('.')
260
+ @dummy.save
261
+ end
262
+
263
+ it 'sets the @fog_public instance variable to false' do
264
+ assert_equal false, @dummy.avatar.instance_variable_get('@options')[:fog_public]
265
+ assert_equal false, @dummy.avatar.fog_public
266
+ end
267
+ end
268
+
269
+ context "with styles set and fog_public set to false" do
270
+ before do
271
+ rebuild_model(@options.merge(fog_public: false, styles: { medium: "300x300>", thumb: "100x100>" }))
272
+ @file = File.new(fixture_file('5k.png'), 'rb')
273
+ @dummy = Dummy.new
274
+ @dummy.avatar = @file
275
+ @dummy.save
276
+ end
277
+
278
+ it 'sets the @fog_public for a particular style to false' do
279
+ assert_equal false, @dummy.avatar.instance_variable_get('@options')[:fog_public]
280
+ assert_equal false, @dummy.avatar.fog_public(:thumb)
281
+ end
282
+ end
283
+
284
+ context "with styles set and fog_public set per-style" do
285
+ before do
286
+ rebuild_model(@options.merge(fog_public: { medium: false, thumb: true}, styles: { medium: "300x300>", thumb: "100x100>" }))
287
+ @file = File.new(fixture_file('5k.png'), 'rb')
288
+ @dummy = Dummy.new
289
+ @dummy.avatar = @file
290
+ @dummy.save
291
+ end
292
+
293
+ it 'sets the fog_public for a particular style to correct value' do
294
+ assert_equal false, @dummy.avatar.fog_public(:medium)
295
+ assert_equal true, @dummy.avatar.fog_public(:thumb)
296
+ end
297
+ end
298
+
299
+ context "with fog_public not set" do
300
+ before do
301
+ rebuild_model(@options)
302
+ @dummy = Dummy.new
303
+ @dummy.avatar = StringIO.new('.')
304
+ @dummy.save
305
+ end
306
+
307
+ it "defaults fog_public to true" do
308
+ assert_equal true, @dummy.avatar.fog_public
309
+ end
310
+ end
311
+
312
+ context "with scheme set" do
313
+ before do
314
+ rebuild_model(@options.merge(:fog_credentials => @credentials.merge(:scheme => 'http')))
315
+ @file = File.new(fixture_file('5k.png'), 'rb')
316
+ @dummy = Dummy.new
317
+ @dummy.avatar = @file
318
+ @dummy.save
319
+ end
320
+
321
+ it "honors the scheme in public url" do
322
+ assert_match(/^http:\/\//, @dummy.avatar.url)
323
+ end
324
+ it "honors the scheme in expiring url" do
325
+ assert_match(/^http:\/\//, @dummy.avatar.expiring_url)
326
+ end
327
+ end
328
+
329
+ context "with scheme not set" do
330
+ before do
331
+ rebuild_model(@options)
332
+ @file = File.new(fixture_file('5k.png'), 'rb')
333
+ @dummy = Dummy.new
334
+ @dummy.avatar = @file
335
+ @dummy.save
336
+ end
337
+
338
+ it "provides HTTPS public url" do
339
+ assert_match(/^https:\/\//, @dummy.avatar.url)
340
+ end
341
+ it "provides HTTPS expiring url" do
342
+ assert_match(/^https:\/\//, @dummy.avatar.expiring_url)
343
+ end
344
+ end
345
+
346
+ context "with a valid bucket name for a subdomain" do
347
+ before { @dummy.stubs(:new_record?).returns(false) }
348
+
349
+ it "provides an url in subdomain style" do
350
+ assert_match(/^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png/, @dummy.avatar.url)
351
+ end
352
+
353
+ it "provides an url that expires in subdomain style" do
354
+ assert_match(/^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
355
+ end
356
+ end
357
+
358
+ context "generating an expiring url" do
359
+ it "generates the same url when using Times and Integer offsets" do
360
+ Timecop.freeze do
361
+ offset = 1234
362
+ rebuild_model(@options)
363
+ dummy = Dummy.new
364
+ dummy.avatar = StringIO.new('.')
365
+
366
+ assert_equal dummy.avatar.expiring_url(offset),
367
+ dummy.avatar.expiring_url(Time.now + offset )
368
+ end
369
+ end
370
+
371
+ it 'matches the default url if there is no assignment' do
372
+ dummy = Dummy.new
373
+ assert_equal dummy.avatar.url, dummy.avatar.expiring_url
374
+ end
375
+
376
+ it 'matches the default url when given a style if there is no assignment' do
377
+ dummy = Dummy.new
378
+ assert_equal dummy.avatar.url(:thumb), dummy.avatar.expiring_url(3600, :thumb)
379
+ end
380
+ end
381
+
382
+ context "with an invalid bucket name for a subdomain" do
383
+ before do
384
+ rebuild_model(@options.merge(fog_directory: "this_is_invalid"))
385
+ @dummy = Dummy.new
386
+ @dummy.avatar = @file
387
+ @dummy.save
388
+ end
389
+
390
+ it "does not match the bucket-subdomain restrictions" do
391
+ invalid_subdomains = %w(this_is_invalid in iamareallylongbucketnameiamareallylongbucketnameiamareallylongbu invalid- inval..id inval-.id inval.-id -invalid 192.168.10.2)
392
+ invalid_subdomains.each do |name|
393
+ assert_no_match Paperclip::Storage::Fog::AWS_BUCKET_SUBDOMAIN_RESTRICTON_REGEX, name
394
+ end
395
+ end
396
+
397
+ it "provides an url in folder style" do
398
+ assert_match(/^https:\/\/s3.amazonaws.com\/this_is_invalid\/avatars\/5k.png\?\d*$/, @dummy.avatar.url)
399
+ end
400
+
401
+ it "provides a url that expires in folder style" do
402
+ assert_match(/^https:\/\/s3.amazonaws.com\/this_is_invalid\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
403
+ end
404
+
405
+ end
406
+
407
+ context "with a proc for a bucket name evaluating a model method" do
408
+ before do
409
+ @dynamic_fog_directory = 'dynamicpaperclip'
410
+ rebuild_model(@options.merge(fog_directory: lambda { |attachment| attachment.instance.bucket_name }))
411
+ @dummy = Dummy.new
412
+ @dummy.stubs(:bucket_name).returns(@dynamic_fog_directory)
413
+ @dummy.avatar = @file
414
+ @dummy.save
415
+ end
416
+
417
+ it "has created the bucket" do
418
+ assert @connection.directories.get(@dynamic_fog_directory).inspect
419
+ end
420
+
421
+ end
422
+
423
+ context "with a proc for the fog_host evaluating a model method" do
424
+ before do
425
+ rebuild_model(@options.merge(fog_host: lambda { |attachment| attachment.instance.fog_host }))
426
+ @dummy = Dummy.new
427
+ @dummy.stubs(:fog_host).returns('http://dynamicfoghost.com')
428
+ @dummy.avatar = @file
429
+ @dummy.save
430
+ end
431
+
432
+ it "provides a public url" do
433
+ assert_match(/http:\/\/dynamicfoghost\.com/, @dummy.avatar.url)
434
+ end
435
+
436
+ end
437
+
438
+ context "with a custom fog_host" do
439
+ before do
440
+ rebuild_model(@options.merge(fog_host: "http://dynamicfoghost.com"))
441
+ @dummy = Dummy.new
442
+ @dummy.avatar = @file
443
+ @dummy.save
444
+ end
445
+
446
+ it "provides a public url" do
447
+ assert_match(/http:\/\/dynamicfoghost\.com/, @dummy.avatar.url)
448
+ end
449
+
450
+ it "provides an expiring url" do
451
+ assert_match(/http:\/\/dynamicfoghost\.com/, @dummy.avatar.expiring_url)
452
+ end
453
+
454
+ context "with an invalid bucket name for a subdomain" do
455
+ before do
456
+ rebuild_model(@options.merge({fog_directory: "this_is_invalid", fog_host: "http://dynamicfoghost.com"}))
457
+ @dummy = Dummy.new
458
+ @dummy.avatar = @file
459
+ @dummy.save
460
+ end
461
+
462
+ it "provides an expiring url" do
463
+ assert_match(/http:\/\/dynamicfoghost\.com/, @dummy.avatar.expiring_url)
464
+ end
465
+ end
466
+
467
+ end
468
+
469
+ context "with a proc for the fog_credentials evaluating a model method" do
470
+ before do
471
+ @dynamic_fog_credentials = {
472
+ provider: 'AWS',
473
+ aws_access_key_id: 'DYNAMIC_ID',
474
+ aws_secret_access_key: 'DYNAMIC_SECRET'
475
+ }
476
+ rebuild_model(@options.merge(fog_credentials: lambda { |attachment| attachment.instance.fog_credentials }))
477
+ @dummy = Dummy.new
478
+ @dummy.stubs(:fog_credentials).returns(@dynamic_fog_credentials)
479
+ @dummy.avatar = @file
480
+ @dummy.save
481
+ end
482
+
483
+ it "provides a public url" do
484
+ assert_equal @dummy.avatar.fog_credentials, @dynamic_fog_credentials
485
+ end
486
+ end
487
+
488
+ context "with custom fog_options" do
489
+ before do
490
+ rebuild_model(
491
+ @options.merge(fog_options: { multipart_chunk_size: 104857600 }),
492
+ )
493
+ @dummy = Dummy.new
494
+ @dummy.avatar = @file
495
+ end
496
+
497
+ it "applies the options to the fog #create call" do
498
+ files = stub
499
+ @dummy.avatar.stubs(:directory).returns stub(files: files)
500
+ files.expects(:create).with(
501
+ has_entries(multipart_chunk_size: 104857600),
502
+ )
503
+ @dummy.save
504
+ end
505
+ end
506
+ end
507
+
508
+ end
509
+
510
+ context "when using local storage" do
511
+ before do
512
+ Fog.unmock!
513
+ rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
514
+ storage: :fog,
515
+ url: '/:attachment/:filename',
516
+ fog_directory: "paperclip",
517
+ fog_credentials: { provider: :local, local_root: "." },
518
+ fog_host: 'localhost'
519
+
520
+ @file = File.new(fixture_file('5k.png'), 'rb')
521
+ @dummy = Dummy.new
522
+ @dummy.avatar = @file
523
+ @dummy.stubs(:new_record?).returns(false)
524
+ end
525
+
526
+ after do
527
+ @file.close
528
+ Fog.mock!
529
+ end
530
+
531
+ it "returns the public url in place of the expiring url" do
532
+ assert_match @dummy.avatar.public_url, @dummy.avatar.expiring_url
533
+ end
534
+ end
535
+ end