carrierwave 0.11.2 → 3.0.3

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

Potentially problematic release.


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

Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +452 -178
  3. data/lib/carrierwave/compatibility/paperclip.rb +4 -4
  4. data/lib/carrierwave/downloader/base.rb +101 -0
  5. data/lib/carrierwave/downloader/remote_file.rb +68 -0
  6. data/lib/carrierwave/error.rb +1 -0
  7. data/lib/carrierwave/locale/en.yml +11 -5
  8. data/lib/carrierwave/mount.rb +212 -182
  9. data/lib/carrierwave/mounter.rb +255 -0
  10. data/lib/carrierwave/orm/activerecord.rb +22 -33
  11. data/lib/carrierwave/processing/mini_magick.rb +140 -84
  12. data/lib/carrierwave/processing/rmagick.rb +72 -21
  13. data/lib/carrierwave/processing/vips.rb +284 -0
  14. data/lib/carrierwave/processing.rb +1 -1
  15. data/lib/carrierwave/sanitized_file.rb +83 -84
  16. data/lib/carrierwave/storage/abstract.rb +16 -3
  17. data/lib/carrierwave/storage/file.rb +71 -3
  18. data/lib/carrierwave/storage/fog.rb +215 -57
  19. data/lib/carrierwave/storage.rb +1 -9
  20. data/lib/carrierwave/test/matchers.rb +88 -19
  21. data/lib/carrierwave/uploader/cache.rb +75 -45
  22. data/lib/carrierwave/uploader/callbacks.rb +1 -3
  23. data/lib/carrierwave/uploader/configuration.rb +80 -16
  24. data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
  25. data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
  26. data/lib/carrierwave/uploader/default_url.rb +3 -5
  27. data/lib/carrierwave/uploader/dimension.rb +66 -0
  28. data/lib/carrierwave/uploader/download.rb +4 -74
  29. data/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
  30. data/lib/carrierwave/uploader/extension_denylist.rb +64 -0
  31. data/lib/carrierwave/uploader/file_size.rb +43 -0
  32. data/lib/carrierwave/uploader/mountable.rb +13 -8
  33. data/lib/carrierwave/uploader/processing.rb +48 -13
  34. data/lib/carrierwave/uploader/proxy.rb +20 -9
  35. data/lib/carrierwave/uploader/remove.rb +0 -2
  36. data/lib/carrierwave/uploader/serialization.rb +2 -4
  37. data/lib/carrierwave/uploader/store.rb +59 -28
  38. data/lib/carrierwave/uploader/url.rb +8 -7
  39. data/lib/carrierwave/uploader/versions.rb +170 -122
  40. data/lib/carrierwave/uploader.rb +12 -10
  41. data/lib/carrierwave/utilities/file_name.rb +47 -0
  42. data/lib/carrierwave/utilities/uri.rb +14 -12
  43. data/lib/carrierwave/utilities.rb +1 -3
  44. data/lib/carrierwave/validations/active_model.rb +7 -11
  45. data/lib/carrierwave/version.rb +1 -1
  46. data/lib/carrierwave.rb +39 -21
  47. data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +5 -9
  48. data/lib/generators/uploader_generator.rb +3 -3
  49. metadata +132 -80
  50. data/lib/carrierwave/locale/cs.yml +0 -11
  51. data/lib/carrierwave/locale/de.yml +0 -11
  52. data/lib/carrierwave/locale/el.yml +0 -11
  53. data/lib/carrierwave/locale/es.yml +0 -11
  54. data/lib/carrierwave/locale/fr.yml +0 -11
  55. data/lib/carrierwave/locale/ja.yml +0 -11
  56. data/lib/carrierwave/locale/nb.yml +0 -11
  57. data/lib/carrierwave/locale/nl.yml +0 -11
  58. data/lib/carrierwave/locale/pl.yml +0 -11
  59. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  60. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  61. data/lib/carrierwave/locale/ru.yml +0 -11
  62. data/lib/carrierwave/locale/sk.yml +0 -11
  63. data/lib/carrierwave/locale/tr.yml +0 -11
  64. data/lib/carrierwave/processing/mime_types.rb +0 -74
  65. data/lib/carrierwave/uploader/content_type_blacklist.rb +0 -48
  66. data/lib/carrierwave/uploader/content_type_whitelist.rb +0 -48
  67. data/lib/carrierwave/uploader/extension_blacklist.rb +0 -47
  68. data/lib/carrierwave/uploader/extension_whitelist.rb +0 -49
  69. data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Test
5
3
 
@@ -23,13 +21,16 @@ module CarrierWave
23
21
  "expected #{@actual.inspect} to be identical to #{@expected.inspect}"
24
22
  end
25
23
 
26
- def negative_failure_message
24
+ def failure_message_when_negated
27
25
  "expected #{@actual.inspect} to not be identical to #{@expected.inspect}"
28
26
  end
29
27
 
30
28
  def description
31
29
  "be identical to #{@expected.inspect}"
32
30
  end
31
+
32
+ # RSpec 2 compatibility:
33
+ alias_method :negative_failure_message, :failure_message_when_negated
33
34
  end
34
35
 
35
36
  def be_identical_to(expected)
@@ -44,20 +45,23 @@ module CarrierWave
44
45
  def matches?(actual)
45
46
  @actual = actual
46
47
  # Satisfy expectation here. Return false or raise an error if it's not met.
47
- (File.stat(@actual.path).mode & 0777) == @expected
48
+ (File.stat(@actual.path).mode & 0o777) == @expected
48
49
  end
49
50
 
50
51
  def failure_message
51
- "expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
52
+ "expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0o777).to_s(8)}"
52
53
  end
53
54
 
54
- def negative_failure_message
55
+ def failure_message_when_negated
55
56
  "expected #{@actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
56
57
  end
57
58
 
58
59
  def description
59
60
  "have permissions #{@expected.to_s(8)}"
60
61
  end
62
+
63
+ # RSpec 2 compatibility:
64
+ alias_method :negative_failure_message, :failure_message_when_negated
61
65
  end
62
66
 
63
67
  def have_permissions(expected)
@@ -72,20 +76,23 @@ module CarrierWave
72
76
  def matches?(actual)
73
77
  @actual = actual
74
78
  # Satisfy expectation here. Return false or raise an error if it's not met.
75
- (File.stat(File.dirname @actual.path).mode & 0777) == @expected
79
+ (File.stat(File.dirname(@actual.path)).mode & 0o777) == @expected
76
80
  end
77
81
 
78
82
  def failure_message
79
- "expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
83
+ "expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0o777).to_s(8)}"
80
84
  end
81
85
 
82
- def negative_failure_message
86
+ def failure_message_when_negated
83
87
  "expected #{File.dirname @actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
84
88
  end
85
89
 
86
90
  def description
87
91
  "have permissions #{@expected.to_s(8)}"
88
92
  end
93
+
94
+ # RSpec 2 compatibility:
95
+ alias_method :negative_failure_message, :failure_message_when_negated
89
96
  end
90
97
 
91
98
  def have_directory_permissions(expected)
@@ -110,13 +117,16 @@ module CarrierWave
110
117
  "expected #{@actual.current_path.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
111
118
  end
112
119
 
113
- def negative_failure_message
120
+ def failure_message_when_negated
114
121
  "expected #{@actual.current_path.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
115
122
  end
116
123
 
117
124
  def description
118
125
  "be no larger than #{@width} by #{@height}"
119
126
  end
127
+
128
+ # RSpec 2 compatibility:
129
+ alias_method :negative_failure_message, :failure_message_when_negated
120
130
  end
121
131
 
122
132
  def be_no_larger_than(width, height)
@@ -141,13 +151,16 @@ module CarrierWave
141
151
  "expected #{@actual.current_path.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
142
152
  end
143
153
 
144
- def negative_failure_message
154
+ def failure_message_when_negated
145
155
  "expected #{@actual.current_path.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
146
156
  end
147
157
 
148
158
  def description
149
159
  "have an exact size of #{@width} by #{@height}"
150
160
  end
161
+
162
+ # RSpec 2 compatibility:
163
+ alias_method :negative_failure_message, :failure_message_when_negated
151
164
  end
152
165
 
153
166
  def have_dimensions(width, height)
@@ -171,13 +184,16 @@ module CarrierWave
171
184
  "expected #{@actual.current_path.inspect} to have an exact size of #{@height}, but it was #{@actual_height}."
172
185
  end
173
186
 
174
- def negative_failure_message
187
+ def failure_message_when_negated
175
188
  "expected #{@actual.current_path.inspect} not to have an exact size of #{@height}, but it did."
176
189
  end
177
190
 
178
191
  def description
179
192
  "have an exact height of #{@height}"
180
193
  end
194
+
195
+ # RSpec 2 compatibility:
196
+ alias_method :negative_failure_message, :failure_message_when_negated
181
197
  end
182
198
 
183
199
  def have_height(height)
@@ -201,13 +217,16 @@ module CarrierWave
201
217
  "expected #{@actual.current_path.inspect} to have an exact size of #{@width}, but it was #{@actual_width}."
202
218
  end
203
219
 
204
- def negative_failure_message
220
+ def failure_message_when_negated
205
221
  "expected #{@actual.current_path.inspect} not to have an exact size of #{@width}, but it did."
206
222
  end
207
223
 
208
224
  def description
209
225
  "have an exact width of #{@width}"
210
226
  end
227
+
228
+ # RSpec 2 compatibility:
229
+ alias_method :negative_failure_message, :failure_message_when_negated
211
230
  end
212
231
 
213
232
  def have_width(width)
@@ -231,13 +250,16 @@ module CarrierWave
231
250
  "expected #{@actual.current_path.inspect} to be no wider than #{@width}, but it was #{@actual_width}."
232
251
  end
233
252
 
234
- def negative_failure_message
253
+ def failure_message_when_negated
235
254
  "expected #{@actual.current_path.inspect} not to be wider than #{@width}, but it is."
236
255
  end
237
256
 
238
257
  def description
239
258
  "have a width less than or equal to #{@width}"
240
259
  end
260
+
261
+ # RSpec 2 compatibility:
262
+ alias_method :negative_failure_message, :failure_message_when_negated
241
263
  end
242
264
 
243
265
  def be_no_wider_than(width)
@@ -261,19 +283,55 @@ module CarrierWave
261
283
  "expected #{@actual.current_path.inspect} to be no taller than #{@height}, but it was #{@actual_height}."
262
284
  end
263
285
 
264
- def negative_failure_message
286
+ def failure_message_when_negated
265
287
  "expected #{@actual.current_path.inspect} not to be taller than #{@height}, but it is."
266
288
  end
267
289
 
268
290
  def description
269
291
  "have a height less than or equal to #{@height}"
270
292
  end
293
+
294
+ # RSpec 2 compatibility:
295
+ alias_method :negative_failure_message, :failure_message_when_negated
271
296
  end
272
297
 
273
298
  def be_no_taller_than(height)
274
299
  BeNoTallerThan.new(height)
275
300
  end
276
301
 
302
+ class BeFormat # :nodoc:
303
+ def initialize(expected)
304
+ @expected = expected
305
+ end
306
+
307
+ def matches?(actual)
308
+ @actual = actual
309
+ # Satisfy expectation here. Return false or raise an error if it's not met.
310
+ image = ImageLoader.load_image(@actual.current_path)
311
+ @actual_expected = image.format
312
+ !@expected.nil? && @actual_expected.casecmp(@expected).zero?
313
+ end
314
+
315
+ def failure_message
316
+ "expected #{@actual.current_path.inspect} to have #{@expected} format, but it was #{@actual_expected}."
317
+ end
318
+
319
+ def failure_message_when_negated
320
+ "expected #{@actual.current_path.inspect} not to have #{@expected} format, but it did."
321
+ end
322
+
323
+ def description
324
+ "have #{@expected} format"
325
+ end
326
+
327
+ # RSpec 2 compatibility:
328
+ alias_method :negative_failure_message, :failure_message_when_negated
329
+ end
330
+
331
+ def be_format(expected)
332
+ BeFormat.new(expected)
333
+ end
334
+
277
335
  class ImageLoader # :nodoc:
278
336
  def self.load_image(filename)
279
337
  if defined? ::MiniMagick
@@ -283,9 +341,11 @@ module CarrierWave
283
341
  begin
284
342
  require 'rmagick'
285
343
  rescue LoadError
286
- require 'RMagick'
287
- rescue LoadError
288
- puts "WARNING: Failed to require rmagick, image processing may fail!"
344
+ begin
345
+ require 'RMagick'
346
+ rescue LoadError
347
+ puts "WARNING: Failed to require rmagick, image processing may fail!"
348
+ end
289
349
  end
290
350
  end
291
351
  MagickWrapper.new(filename)
@@ -295,6 +355,7 @@ module CarrierWave
295
355
 
296
356
  class MagickWrapper # :nodoc:
297
357
  attr_reader :image
358
+
298
359
  def width
299
360
  image.columns
300
361
  end
@@ -303,6 +364,10 @@ module CarrierWave
303
364
  image.rows
304
365
  end
305
366
 
367
+ def format
368
+ image.format
369
+ end
370
+
306
371
  def initialize(filename)
307
372
  @image = ::Magick::Image.read(filename).first
308
373
  end
@@ -310,6 +375,7 @@ module CarrierWave
310
375
 
311
376
  class MiniMagickWrapper # :nodoc:
312
377
  attr_reader :image
378
+
313
379
  def width
314
380
  image[:width]
315
381
  end
@@ -318,6 +384,10 @@ module CarrierWave
318
384
  image[:height]
319
385
  end
320
386
 
387
+ def format
388
+ image[:format]
389
+ end
390
+
321
391
  def initialize(filename)
322
392
  @image = ::MiniMagick::Image.open(filename)
323
393
  end
@@ -326,4 +396,3 @@ module CarrierWave
326
396
  end # Matchers
327
397
  end # Test
328
398
  end # CarrierWave
329
-
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ require 'securerandom'
2
2
 
3
3
  module CarrierWave
4
4
 
@@ -24,10 +24,11 @@ module CarrierWave
24
24
  # [String] a cache id in the format TIMEINT-PID-COUNTER-RND
25
25
  #
26
26
  def self.generate_cache_id
27
- [Time.now.utc.to_i,
28
- Process.pid,
29
- '%04d' % (CarrierWave::CacheCounter.increment % 1000),
30
- '%04d' % rand(9999)
27
+ [
28
+ Time.now.utc.to_i,
29
+ SecureRandom.random_number(1_000_000_000_000_000),
30
+ '%04d' % (CarrierWave::CacheCounter.increment % 10_000),
31
+ '%04d' % SecureRandom.random_number(10_000)
31
32
  ].map(&:to_s).join('-')
32
33
  end
33
34
 
@@ -38,6 +39,16 @@ module CarrierWave
38
39
  include CarrierWave::Uploader::Callbacks
39
40
  include CarrierWave::Uploader::Configuration
40
41
 
42
+ included do
43
+ prepend Module.new {
44
+ def initialize(*)
45
+ super
46
+ @staged = false
47
+ end
48
+ }
49
+ attr_accessor :staged
50
+ end
51
+
41
52
  module ClassMethods
42
53
 
43
54
  ##
@@ -54,13 +65,7 @@ module CarrierWave
54
65
  # It's recommended that you keep cache files in one place only.
55
66
  #
56
67
  def clean_cached_files!(seconds=60*60*24)
57
- Dir.glob(File.expand_path(File.join(cache_dir, '*'), CarrierWave.root)).each do |dir|
58
- time = dir.scan(/(\d+)-\d+-\d+/).first.map { |t| t.to_i }
59
- time = Time.at(*time)
60
- if time < (Time.now.utc - seconds)
61
- FileUtils.rm_rf(dir)
62
- end
63
- end
68
+ (cache_storage || storage).new(new).clean_cache!(seconds)
64
69
  end
65
70
  end
66
71
 
@@ -72,7 +77,7 @@ module CarrierWave
72
77
  # [Bool] whether the current file is cached
73
78
  #
74
79
  def cached?
75
- @cache_id
80
+ !!@cache_id
76
81
  end
77
82
 
78
83
  ##
@@ -86,16 +91,8 @@ module CarrierWave
86
91
  end
87
92
 
88
93
  def sanitized_file
89
- _content = file.read
90
- if _content.is_a?(File) # could be if storage is Fog
91
- sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
92
- sanitized.read if sanitized.exists?
93
-
94
- else
95
- sanitized = SanitizedFile.new :tempfile => StringIO.new(file.read),
96
- :filename => File.basename(path), :content_type => file.content_type
97
- end
98
- sanitized
94
+ ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
95
+ file
99
96
  end
100
97
 
101
98
  ##
@@ -106,7 +103,7 @@ module CarrierWave
106
103
  # [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
107
104
  #
108
105
  def cache_name
109
- File.join(cache_id, full_original_filename) if cache_id and original_filename
106
+ File.join(cache_id, original_filename) if cache_id && original_filename
110
107
  end
111
108
 
112
109
  ##
@@ -114,7 +111,7 @@ module CarrierWave
114
111
  #
115
112
  # By default, cache!() uses copy_to(), which operates by copying the file
116
113
  # to the cache, then deleting the original file. If move_to_cache() is
117
- # overriden to return true, then cache!() uses move_to(), which simply
114
+ # overridden to return true, then cache!() uses move_to(), which simply
118
115
  # moves the file to the cache. Useful for large files.
119
116
  #
120
117
  # === Parameters
@@ -125,24 +122,32 @@ module CarrierWave
125
122
  #
126
123
  # [CarrierWave::FormNotMultipart] if the assigned parameter is a string
127
124
  #
128
- def cache!(new_file = sanitized_file)
125
+ def cache!(new_file = file)
129
126
  new_file = CarrierWave::SanitizedFile.new(new_file)
127
+ return if new_file.empty?
128
+
129
+ raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
130
130
 
131
- unless new_file.empty?
132
- raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
131
+ self.cache_id = CarrierWave.generate_cache_id unless cache_id
133
132
 
134
- with_callbacks(:cache, new_file) do
135
- self.cache_id = CarrierWave.generate_cache_id unless cache_id
133
+ @identifier = nil
134
+ @staged = true
135
+ @filename = new_file.filename
136
+ self.original_filename = new_file.filename
136
137
 
137
- @filename = new_file.filename
138
- self.original_filename = new_file.filename
138
+ begin
139
+ # first, create a workfile on which we perform processings
140
+ if move_to_cache
141
+ @file = new_file.move_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
142
+ else
143
+ @file = new_file.copy_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
144
+ end
139
145
 
140
- if move_to_cache
141
- @file = new_file.move_to(cache_path, permissions, directory_permissions)
142
- else
143
- @file = new_file.copy_to(cache_path, permissions, directory_permissions)
144
- end
146
+ with_callbacks(:cache, @file) do
147
+ @file = cache_storage.cache!(@file)
145
148
  end
149
+ ensure
150
+ FileUtils.rm_rf(workfile_path(''))
146
151
  end
147
152
  end
148
153
 
@@ -160,26 +165,43 @@ module CarrierWave
160
165
  def retrieve_from_cache!(cache_name)
161
166
  with_callbacks(:retrieve_from_cache, cache_name) do
162
167
  self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
168
+ @staged = true
163
169
  @filename = original_filename
164
- @file = CarrierWave::SanitizedFile.new(cache_path)
170
+ @file = cache_storage.retrieve_from_cache!(full_original_filename)
165
171
  end
166
172
  end
167
173
 
174
+ ##
175
+ # Calculates the path where the cache file should be stored.
176
+ #
177
+ # === Parameters
178
+ #
179
+ # [for_file (String)] name of the file <optional>
180
+ #
181
+ # === Returns
182
+ #
183
+ # [String] the cache path
184
+ #
185
+ def cache_path(for_file=full_original_filename)
186
+ File.join(*[cache_dir, @cache_id, for_file].compact)
187
+ end
188
+
189
+ protected
190
+
191
+ attr_reader :cache_id
192
+
168
193
  private
169
194
 
170
- def cache_path
171
- File.expand_path(File.join(cache_dir, cache_name), root)
195
+ def workfile_path(for_file=original_filename)
196
+ File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
172
197
  end
173
198
 
174
- attr_reader :cache_id, :original_filename
175
-
176
- # We can override the full_original_filename method in other modules
177
- alias_method :full_original_filename, :original_filename
199
+ attr_reader :original_filename
178
200
 
179
201
  def cache_id=(cache_id)
180
202
  # Earlier version used 3 part cache_id. Thus we should allow for
181
203
  # the cache_id to have both 3 part and 4 part formats.
182
- raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]+\-[\d]+(\-[\d]{4})?\-[\d]{4}\z/
204
+ raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A(-)?[\d]+\-[\d]+(\-[\d]{4})?\-[\d]{4}\z/
183
205
  @cache_id = cache_id
184
206
  end
185
207
 
@@ -188,6 +210,14 @@ module CarrierWave
188
210
  @original_filename = filename
189
211
  end
190
212
 
213
+ def cache_storage
214
+ @cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
215
+ end
216
+
217
+ # We can override the full_original_filename method in other modules
218
+ def full_original_filename
219
+ forcing_extension(original_filename)
220
+ end
191
221
  end # Cache
192
222
  end # Uploader
193
223
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Uploader
5
3
  module Callbacks
@@ -7,7 +5,7 @@ module CarrierWave
7
5
 
8
6
  included do
9
7
  class_attribute :_before_callbacks, :_after_callbacks,
10
- :instance_writer => false
8
+ :instance_writer => false
11
9
  self._before_callbacks = Hash.new []
12
10
  self._after_callbacks = Hash.new []
13
11
  end
@@ -1,3 +1,5 @@
1
+ require 'carrierwave/downloader/base'
2
+
1
3
  module CarrierWave
2
4
 
3
5
  module Uploader
@@ -5,7 +7,7 @@ module CarrierWave
5
7
  extend ActiveSupport::Concern
6
8
 
7
9
  included do
8
- class_attribute :_storage, :instance_writer => false
10
+ class_attribute :_storage, :_cache_storage, :instance_writer => false
9
11
 
10
12
  add_config :root
11
13
  add_config :base_path
@@ -21,14 +23,18 @@ module CarrierWave
21
23
  add_config :move_to_cache
22
24
  add_config :move_to_store
23
25
  add_config :remove_previously_stored_files_after_update
26
+ add_config :downloader
27
+ add_config :force_extension
24
28
 
25
29
  # fog
30
+ add_deprecated_config :fog_provider
26
31
  add_config :fog_attributes
27
32
  add_config :fog_credentials
28
33
  add_config :fog_directory
29
34
  add_config :fog_public
30
35
  add_config :fog_authenticated_url_expiration
31
36
  add_config :fog_use_ssl_for_aws
37
+ add_config :fog_aws_accelerate
32
38
 
33
39
  # Mounting
34
40
  add_config :ignore_integrity_errors
@@ -38,6 +44,9 @@ module CarrierWave
38
44
  add_config :validate_processing
39
45
  add_config :validate_download
40
46
  add_config :mount_on
47
+ add_config :cache_only
48
+ add_config :download_retry_count
49
+ add_config :download_retry_wait_time
41
50
 
42
51
  # set default values
43
52
  reset_config
@@ -69,36 +78,66 @@ module CarrierWave
69
78
  # storage MyCustomStorageEngine
70
79
  #
71
80
  def storage(storage = nil)
72
- if storage
73
- self._storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
81
+ case storage
82
+ when Symbol
83
+ if (storage_engine = storage_engines[storage])
84
+ self._storage = eval storage_engine
85
+ else
86
+ raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
87
+ end
88
+ when nil
89
+ storage
90
+ else
91
+ self._storage = storage
74
92
  end
75
93
  _storage
76
94
  end
77
95
  alias_method :storage=, :storage
78
96
 
97
+ ##
98
+ # Sets the cache storage engine to be used when storing cache files with this uploader.
99
+ # Same as .storage except for required methods being #cache!(CarrierWave::SanitizedFile),
100
+ # #retrieve_from_cache! and #delete_dir!.
101
+ #
102
+ # === Parameters
103
+ #
104
+ # [storage (Symbol, Class)] The cache storage engine to use for this uploader
105
+ #
106
+ # === Returns
107
+ #
108
+ # [Class] the cache storage engine to be used with this uploader
109
+ #
110
+ # === Examples
111
+ #
112
+ # cache_storage :file
113
+ # cache_storage CarrierWave::Storage::File
114
+ # cache_storage MyCustomStorageEngine
115
+ #
116
+ def cache_storage(storage = false)
117
+ unless storage == false
118
+ self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
119
+ end
120
+ _cache_storage
121
+ end
122
+ alias_method :cache_storage=, :cache_storage
123
+
79
124
  def add_config(name)
80
125
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
81
- def self.eager_load_fog(fog_credentials)
82
- # see #1198. This will hopefully no longer be necessary after fog 2.0
83
- Fog::Storage.new(fog_credentials) if fog_credentials.present?
84
- end
126
+ @#{name} = nil
85
127
 
86
128
  def self.#{name}(value=nil)
87
- @#{name} = value if value
88
- eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
129
+ @#{name} = value unless value.nil?
89
130
  return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
90
131
  name = superclass.#{name}
91
- return nil if name.nil? && !instance_variable_defined?("@#{name}")
132
+ return nil if name.nil? && !instance_variable_defined?(:@#{name})
92
133
  @#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
93
134
  end
94
135
 
95
136
  def self.#{name}=(value)
96
- eager_load_fog(value) if '#{name}' == 'fog_credentials'
97
137
  @#{name} = value
98
138
  end
99
139
 
100
140
  def #{name}=(value)
101
- self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials'
102
141
  @#{name} = value
103
142
  end
104
143
 
@@ -107,13 +146,33 @@ module CarrierWave
107
146
  value = self.class.#{name} unless instance_variable_defined?(:@#{name})
108
147
  if value.instance_of?(Proc)
109
148
  value.arity >= 1 ? value.call(self) : value.call
110
- else
149
+ else
111
150
  value
112
151
  end
113
152
  end
114
153
  RUBY
115
154
  end
116
155
 
156
+ def add_deprecated_config(name)
157
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
158
+ def self.#{name}(value=nil)
159
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
160
+ end
161
+
162
+ def self.#{name}=(value)
163
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
164
+ end
165
+
166
+ def #{name}=(value)
167
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
168
+ end
169
+
170
+ def #{name}
171
+ ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
172
+ end
173
+ RUBY
174
+ end
175
+
117
176
  def configure
118
177
  yield self
119
178
  end
@@ -123,24 +182,28 @@ module CarrierWave
123
182
  #
124
183
  def reset_config
125
184
  configure do |config|
126
- config.permissions = 0644
127
- config.directory_permissions = 0755
185
+ config.permissions = 0o644
186
+ config.directory_permissions = 0o755
128
187
  config.storage_engines = {
129
188
  :file => "CarrierWave::Storage::File",
130
189
  :fog => "CarrierWave::Storage::Fog"
131
190
  }
132
191
  config.storage = :file
192
+ config.cache_storage = nil
133
193
  config.fog_attributes = {}
134
194
  config.fog_credentials = {}
135
195
  config.fog_public = true
136
196
  config.fog_authenticated_url_expiration = 600
137
197
  config.fog_use_ssl_for_aws = true
198
+ config.fog_aws_accelerate = false
138
199
  config.store_dir = 'uploads'
139
200
  config.cache_dir = 'uploads/tmp'
140
201
  config.delete_tmp_file_after_storage = true
141
202
  config.move_to_cache = false
142
203
  config.move_to_store = false
143
204
  config.remove_previously_stored_files_after_update = true
205
+ config.downloader = CarrierWave::Downloader::Base
206
+ config.force_extension = false
144
207
  config.ignore_integrity_errors = true
145
208
  config.ignore_processing_errors = true
146
209
  config.ignore_download_errors = true
@@ -151,6 +214,8 @@ module CarrierWave
151
214
  config.base_path = CarrierWave.base_path
152
215
  config.enable_processing = true
153
216
  config.ensure_multipart_form = true
217
+ config.download_retry_count = 0
218
+ config.download_retry_wait_time = 5
154
219
  end
155
220
  end
156
221
  end
@@ -158,4 +223,3 @@ module CarrierWave
158
223
  end
159
224
  end
160
225
  end
161
-