carrierwave 1.3.3 → 2.0.0.rc

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.

@@ -21,9 +21,11 @@ module CarrierWave
21
21
  # process :resize_to_fit => [200, 200]
22
22
  # end
23
23
  #
24
- # Or create your own helpers with the powerful manipulate! method. Check
25
- # out the ImageMagick docs at http://www.imagemagick.org/script/command-line-options.php for more
26
- # info
24
+ # Or create your own helpers with the powerful minimagick! method, which
25
+ # yields an ImageProcessing::Builder object. Check out the ImageProcessing
26
+ # docs at http://github.com/janko-m/image_processing and the list of all
27
+ # available ImageMagick options at
28
+ # http://www.imagemagick.org/script/command-line-options.php for more info.
27
29
  #
28
30
  # class MyUploader < CarrierWave::Uploader::Base
29
31
  # include CarrierWave::MiniMagick
@@ -31,23 +33,22 @@ module CarrierWave
31
33
  # process :radial_blur => 10
32
34
  #
33
35
  # def radial_blur(amount)
34
- # manipulate! do |img|
35
- # img.radial_blur(amount)
36
- # img = yield(img) if block_given?
37
- # img
36
+ # minimagick! do |builder|
37
+ # builder.radial_blur(amount)
38
+ # builder = yield(builder) if block_given?
39
+ # builder
38
40
  # end
39
41
  # end
40
42
  # end
41
43
  #
42
44
  # === Note
43
45
  #
44
- # MiniMagick is a mini replacement for RMagick that uses the command line
45
- # tool "mogrify" for image manipulation.
46
+ # The ImageProcessing gem uses MiniMagick, a mini replacement for RMagick
47
+ # that uses ImageMagick command-line tools, to build a "convert" command that
48
+ # performs the processing.
46
49
  #
47
50
  # You can find more information here:
48
51
  #
49
- # http://mini_magick.rubyforge.org/
50
- # and
51
52
  # https://github.com/minimagick/minimagick/
52
53
  #
53
54
  #
@@ -55,19 +56,7 @@ module CarrierWave
55
56
  extend ActiveSupport::Concern
56
57
 
57
58
  included do
58
- begin
59
- require "mini_magick"
60
- rescue LoadError => e
61
- e.message << " (You may need to install the mini_magick gem)"
62
- raise e
63
- end
64
-
65
- prepend Module.new {
66
- def initialize(*)
67
- super
68
- @format = nil
69
- end
70
- }
59
+ require "image_processing/mini_magick"
71
60
  end
72
61
 
73
62
  module ClassMethods
@@ -109,12 +98,11 @@ module CarrierWave
109
98
  #
110
99
  # image.convert(:png)
111
100
  #
112
- def convert(format, page=nil)
113
- @format = format
114
- @page = page
115
- manipulate! do |img|
116
- img = yield(img) if block_given?
117
- img
101
+ def convert(format, page=nil, &block)
102
+ minimagick!(block) do |builder|
103
+ builder = builder.convert(format)
104
+ builder = builder.loader(page: page) if page
105
+ builder
118
106
  end
119
107
  end
120
108
 
@@ -128,21 +116,18 @@ module CarrierWave
128
116
  #
129
117
  # [width (Integer)] the width to scale the image to
130
118
  # [height (Integer)] the height to scale the image to
119
+ # [combine_options (Hash)] additional ImageMagick options to apply before resizing
131
120
  #
132
121
  # === Yields
133
122
  #
134
123
  # [MiniMagick::Image] additional manipulations to perform
135
124
  #
136
- def resize_to_limit(width, height, combine_options: {})
137
- width = dimension_from width
138
- height = dimension_from height
139
- manipulate! do |img|
140
- img.combine_options do |cmd|
141
- cmd.resize "#{width}x#{height}>"
142
- append_combine_options cmd, combine_options
143
- end
144
- img = yield(img) if block_given?
145
- img
125
+ def resize_to_limit(width, height, combine_options: {}, &block)
126
+ width, height = resolve_dimensions(width, height)
127
+
128
+ minimagick!(block) do |builder|
129
+ builder.resize_to_limit(width, height)
130
+ .apply(combine_options)
146
131
  end
147
132
  end
148
133
 
@@ -155,21 +140,18 @@ module CarrierWave
155
140
  #
156
141
  # [width (Integer)] the width to scale the image to
157
142
  # [height (Integer)] the height to scale the image to
143
+ # [combine_options (Hash)] additional ImageMagick options to apply before resizing
158
144
  #
159
145
  # === Yields
160
146
  #
161
147
  # [MiniMagick::Image] additional manipulations to perform
162
148
  #
163
- def resize_to_fit(width, height, combine_options: {})
164
- width = dimension_from width
165
- height = dimension_from height
166
- manipulate! do |img|
167
- img.combine_options do |cmd|
168
- cmd.resize "#{width}x#{height}"
169
- append_combine_options cmd, combine_options
170
- end
171
- img = yield(img) if block_given?
172
- img
149
+ def resize_to_fit(width, height, combine_options: {}, &block)
150
+ width, height = resolve_dimensions(width, height)
151
+
152
+ minimagick!(block) do |builder|
153
+ builder.resize_to_fit(width, height)
154
+ .apply(combine_options)
173
155
  end
174
156
  end
175
157
 
@@ -183,37 +165,18 @@ module CarrierWave
183
165
  # [width (Integer)] the width to scale the image to
184
166
  # [height (Integer)] the height to scale the image to
185
167
  # [gravity (String)] the current gravity suggestion (default: 'Center'; options: 'NorthWest', 'North', 'NorthEast', 'West', 'Center', 'East', 'SouthWest', 'South', 'SouthEast')
168
+ # [combine_options (Hash)] additional ImageMagick options to apply before resizing
186
169
  #
187
170
  # === Yields
188
171
  #
189
172
  # [MiniMagick::Image] additional manipulations to perform
190
173
  #
191
- def resize_to_fill(width, height, gravity = 'Center', combine_options: {})
192
- width = dimension_from width
193
- height = dimension_from height
194
- manipulate! do |img|
195
- cols, rows = img[:dimensions]
196
- img.combine_options do |cmd|
197
- if width != cols || height != rows
198
- scale_x = width/cols.to_f
199
- scale_y = height/rows.to_f
200
- if scale_x >= scale_y
201
- cols = (scale_x * (cols + 0.5)).round
202
- rows = (scale_x * (rows + 0.5)).round
203
- cmd.resize "#{cols}"
204
- else
205
- cols = (scale_y * (cols + 0.5)).round
206
- rows = (scale_y * (rows + 0.5)).round
207
- cmd.resize "x#{rows}"
208
- end
209
- end
210
- cmd.gravity gravity
211
- cmd.background "rgba(255,255,255,0.0)"
212
- cmd.extent "#{width}x#{height}" if cols != width || rows != height
213
- append_combine_options cmd, combine_options
214
- end
215
- img = yield(img) if block_given?
216
- img
174
+ def resize_to_fill(width, height, gravity = 'Center', combine_options: {}, &block)
175
+ width, height = resolve_dimensions(width, height)
176
+
177
+ minimagick!(block) do |builder|
178
+ builder.resize_to_fill(width, height, gravity: gravity)
179
+ .apply(combine_options)
217
180
  end
218
181
  end
219
182
 
@@ -232,28 +195,18 @@ module CarrierWave
232
195
  # [height (Integer)] the height to scale the image to
233
196
  # [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
234
197
  # [gravity (String)] how to position the image
198
+ # [combine_options (Hash)] additional ImageMagick options to apply before resizing
235
199
  #
236
200
  # === Yields
237
201
  #
238
202
  # [MiniMagick::Image] additional manipulations to perform
239
203
  #
240
- def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {})
241
- width = dimension_from width
242
- height = dimension_from height
243
- manipulate! do |img|
244
- img.combine_options do |cmd|
245
- cmd.thumbnail "#{width}x#{height}>"
246
- if background == :transparent
247
- cmd.background "rgba(255, 255, 255, 0.0)"
248
- else
249
- cmd.background background
250
- end
251
- cmd.gravity gravity
252
- cmd.extent "#{width}x#{height}"
253
- append_combine_options cmd, combine_options
254
- end
255
- img = yield(img) if block_given?
256
- img
204
+ def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {}, &block)
205
+ width, height = resolve_dimensions(width, height)
206
+
207
+ minimagick!(block) do |builder|
208
+ builder.resize_and_pad(width, height, background: background, gravity: gravity)
209
+ .apply(combine_options)
257
210
  end
258
211
  end
259
212
 
@@ -284,6 +237,9 @@ module CarrierWave
284
237
  # and then pass each of its frames to the supplied block. It will then
285
238
  # save the image to disk.
286
239
  #
240
+ # NOTE: This method exists mostly for backwards compatibility, you should
241
+ # probably use #minimagick!.
242
+ #
287
243
  # === Gotcha
288
244
  #
289
245
  # This method assumes that the object responds to +current_path+.
@@ -303,20 +259,55 @@ module CarrierWave
303
259
  cache_stored_file! if !cached?
304
260
  image = ::MiniMagick::Image.open(current_path)
305
261
 
306
- begin
307
- image.format(@format.to_s.downcase, @page) if @format
308
- image = yield(image)
309
- image.write(current_path)
262
+ image = yield(image)
263
+ FileUtils.mv image.path, current_path
310
264
 
311
- if @format
312
- move_to = current_path.chomp(File.extname(current_path)) + ".#{@format}"
313
- file.content_type = ::MIME::Types.type_for(move_to).first.to_s
314
- file.move_to(move_to, permissions, directory_permissions)
315
- end
265
+ image.run_command("identify", current_path)
266
+ rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
267
+ message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e)
268
+ raise CarrierWave::ProcessingError, message
269
+ ensure
270
+ image.destroy! if image
271
+ end
316
272
 
317
- image.run_command("identify", current_path)
318
- ensure
319
- image.destroy!
273
+ # Process the image with MiniMagick, using the ImageProcessing gem. This
274
+ # method will build a "convert" ImageMagick command and execute it on the
275
+ # current image.
276
+ #
277
+ # === Gotcha
278
+ #
279
+ # This method assumes that the object responds to +current_path+.
280
+ # Any class that this module is mixed into must have a +current_path+ method.
281
+ # CarrierWave::Uploader does, so you won't need to worry about this in
282
+ # most cases.
283
+ #
284
+ # === Yields
285
+ #
286
+ # [ImageProcessing::Builder] use it to define processing to be performed
287
+ #
288
+ # === Raises
289
+ #
290
+ # [CarrierWave::ProcessingError] if processing failed.
291
+ def minimagick!(block = nil)
292
+ builder = ImageProcessing::MiniMagick.source(current_path)
293
+ builder = yield(builder)
294
+
295
+ result = builder.call
296
+ result.close
297
+
298
+ # backwards compatibility (we want to eventually move away from MiniMagick::Image)
299
+ if block
300
+ image = MiniMagick::Image.new(result.path, result)
301
+ image = block.call(image)
302
+ result = image.instance_variable_get(:@tempfile)
303
+ end
304
+
305
+ FileUtils.mv result.path, current_path
306
+
307
+ if File.extname(result.path) != File.extname(current_path)
308
+ move_to = current_path.chomp(File.extname(current_path)) + File.extname(result.path)
309
+ file.content_type = ::MiniMime.lookup_by_filename(move_to).content_type
310
+ file.move_to(move_to, permissions, directory_permissions)
320
311
  end
321
312
  rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
322
313
  message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e)
@@ -325,21 +316,13 @@ module CarrierWave
325
316
 
326
317
  private
327
318
 
328
- def append_combine_options(cmd, combine_options)
329
- combine_options.each do |method, options|
330
- if options.nil?
331
- cmd.send(method)
332
- else
333
- cmd.send(method, options)
334
- end
319
+ def resolve_dimensions(*dimensions)
320
+ dimensions.map do |value|
321
+ next value unless value.instance_of?(Proc)
322
+ value.arity >= 1 ? value.call(self) : value.call
335
323
  end
336
324
  end
337
325
 
338
- def dimension_from(value)
339
- return value unless value.instance_of?(Proc)
340
- value.arity >= 1 ? value.call(self) : value.call
341
- end
342
-
343
326
  def mini_magick_image
344
327
  ::MiniMagick::Image.read(read)
345
328
  end
@@ -363,7 +363,7 @@ module CarrierWave
363
363
  if options[:format] || @format
364
364
  frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
365
365
  move_to = current_path.chomp(File.extname(current_path)) + ".#{options[:format] || @format}"
366
- file.content_type = ::MIME::Types.type_for(move_to).first.to_s
366
+ file.content_type = ::MiniMime.lookup_by_filename(move_to).content_type
367
367
  file.move_to(move_to, permissions, directory_permissions)
368
368
  else
369
369
  frames.write(current_path, &write_block)
@@ -378,15 +378,9 @@ module CarrierWave
378
378
 
379
379
  def create_info_block(options)
380
380
  return nil unless options
381
- proc do |img|
382
- options.each do |k, v|
383
- if v.is_a?(String) && (matches = v.match(/^["'](.+)["']/))
384
- ActiveSupport::Deprecation.warn "Passing quoted strings like #{v} to #manipulate! is deprecated, pass them without quoting."
385
- v = matches[1]
386
- end
387
- img.public_send(:"#{k}=", v)
388
- end
389
- end
381
+ assignments = options.map { |k, v| "self.#{k} = #{v}" }
382
+ code = "lambda { |img| " + assignments.join(";") + "}"
383
+ eval code
390
384
  end
391
385
 
392
386
  def destroy_image(image)
@@ -1,12 +1,7 @@
1
1
  require 'pathname'
2
2
  require 'active_support/core_ext/string/multibyte'
3
-
4
- begin
5
- # Use mime/types/columnar if available, for reduced memory usage
6
- require 'mime/types/columnar'
7
- rescue LoadError
8
- require 'mime/types'
9
- end
3
+ require 'mini_mime'
4
+ require 'mimemagic'
10
5
 
11
6
  module CarrierWave
12
7
 
@@ -264,12 +259,10 @@ module CarrierWave
264
259
  # [String] the content type of the file
265
260
  #
266
261
  def content_type
267
- return @content_type if @content_type
268
- if @file.respond_to?(:content_type) and @file.content_type
269
- @content_type = @file.content_type.to_s.chomp
270
- elsif path
271
- @content_type = ::MIME::Types.type_for(path).first.to_s
272
- end
262
+ @content_type ||=
263
+ existing_content_type ||
264
+ mime_magic_content_type ||
265
+ mini_mime_content_type
273
266
  end
274
267
 
275
268
  ##
@@ -312,7 +305,7 @@ module CarrierWave
312
305
  def mkdir!(path, directory_permissions)
313
306
  options = {}
314
307
  options[:mode] = directory_permissions if directory_permissions
315
- FileUtils.mkdir_p(File.dirname(path), **options) unless File.exist?(File.dirname(path))
308
+ FileUtils.mkdir_p(File.dirname(path), options) unless File.exist?(File.dirname(path))
316
309
  end
317
310
 
318
311
  def chmod!(path, permissions)
@@ -325,10 +318,32 @@ module CarrierWave
325
318
  name = File.basename(name)
326
319
  name = name.gsub(sanitize_regexp,"_")
327
320
  name = "_#{name}" if name =~ /\A\.+\z/
328
- name = "unnamed" if name.size == 0
321
+ name = "unnamed" if name.size.zero?
329
322
  return name.mb_chars.to_s
330
323
  end
331
324
 
325
+ def existing_content_type
326
+ if @file.respond_to?(:content_type) && @file.content_type
327
+ @file.content_type.to_s.chomp
328
+ end
329
+ end
330
+
331
+ def mime_magic_content_type
332
+ if path
333
+ File.open(path) do |file|
334
+ MimeMagic.by_magic(file).try(:type) || 'invalid/invalid'
335
+ end
336
+ end
337
+ rescue Errno::ENOENT
338
+ nil
339
+ end
340
+
341
+ def mini_mime_content_type
342
+ return unless path
343
+ mime_type = ::MiniMime.lookup_by_filename(path)
344
+ @content_type = (mime_type && mime_type.content_type).to_s
345
+ end
346
+
332
347
  def split_extension(filename)
333
348
  # regular expressions to try for identifying extensions
334
349
  extension_matchers = [
@@ -110,8 +110,8 @@ module CarrierWave
110
110
 
111
111
  def clean_cache!(seconds)
112
112
  Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), CarrierWave.root)).each do |dir|
113
- # generate_cache_id returns key formated TIMEINT-PID-COUNTER-RND
114
- time = dir.scan(/(\d+)-\d+-\d+-\d+/).first.map(&:to_i)
113
+ # generate_cache_id returns key formated TIMEINT-PID(-COUNTER)-RND
114
+ time = dir.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first.map(&:to_i)
115
115
  time = Time.at(*time)
116
116
  if time < (Time.now.utc - seconds)
117
117
  FileUtils.rm_rf(dir)
@@ -60,6 +60,14 @@ module CarrierWave
60
60
  def connection_cache
61
61
  @connection_cache ||= {}
62
62
  end
63
+
64
+ def eager_load
65
+ # see #1198. This will hopefully no longer be necessary in future release of fog
66
+ fog_credentials = CarrierWave::Uploader::Base.fog_credentials
67
+ if fog_credentials.present?
68
+ CarrierWave::Storage::Fog.connection_cache[fog_credentials] ||= ::Fog::Storage.new(fog_credentials)
69
+ end
70
+ end
63
71
  end
64
72
 
65
73
  ##
@@ -138,8 +146,8 @@ module CarrierWave
138
146
  :key => uploader.fog_directory,
139
147
  :public => uploader.fog_public
140
148
  ).files.all(:prefix => uploader.cache_dir).each do |file|
141
- # generate_cache_id returns key formated TIMEINT-PID-COUNTER-RND
142
- time = file.key.scan(/(\d+)-\d+-\d+-\d+/).first.map { |t| t.to_i }
149
+ # generate_cache_id returns key formated TIMEINT-PID(-COUNTER)-RND
150
+ time = file.key.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first.map { |t| t.to_i }
143
151
  time = Time.at(*time)
144
152
  file.destroy if time < (Time.now.utc - seconds)
145
153
  end
@@ -177,7 +185,7 @@ module CarrierWave
177
185
 
178
186
  ##
179
187
  # Return a temporary authenticated url to a private file, if available
180
- # Only supported for AWS, Rackspace, Google and AzureRM providers
188
+ # Only supported for AWS, Rackspace, Google, AzureRM and Aliyun providers
181
189
  #
182
190
  # === Returns
183
191
  #
@@ -186,11 +194,11 @@ module CarrierWave
186
194
  # [NilClass] no authenticated url available
187
195
  #
188
196
  def authenticated_url(options = {})
189
- if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM'].include?(@uploader.fog_credentials[:provider])
197
+ if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun'].include?(@uploader.fog_credentials[:provider])
190
198
  # avoid a get by using local references
191
199
  local_directory = connection.directories.new(:key => @uploader.fog_directory)
192
200
  local_file = local_directory.files.new(:key => path)
193
- expire_at = ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
201
+ expire_at = options[:expire_at] || ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
194
202
  case @uploader.fog_credentials[:provider]
195
203
  when 'AWS', 'Google'
196
204
  # Older versions of fog-google do not support options as a parameter
@@ -202,6 +210,9 @@ module CarrierWave
202
210
  end
203
211
  when 'Rackspace', 'OpenStack'
204
212
  connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
213
+ when 'Aliyun'
214
+ expire_at = expire_at - Time.now
215
+ local_file.url(expire_at)
205
216
  else
206
217
  local_file.url(expire_at)
207
218
  end
@@ -216,7 +227,7 @@ module CarrierWave
216
227
  # [String] value of content-type
217
228
  #
218
229
  def content_type
219
- @content_type || !file.nil? && file.content_type
230
+ @content_type || file.try(:content_type)
220
231
  end
221
232
 
222
233
  ##
@@ -239,7 +250,9 @@ module CarrierWave
239
250
  #
240
251
  def delete
241
252
  # avoid a get by just using local reference
242
- directory.files.new(:key => path).destroy
253
+ directory.files.new(:key => path).destroy.tap do |result|
254
+ @file = nil if result
255
+ end
243
256
  end
244
257
 
245
258
  ##
@@ -1,2 +1,3 @@
1
1
  require "carrierwave/storage/abstract"
2
2
  require "carrierwave/storage/file"
3
+ require "carrierwave/storage/fog"
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module CarrierWave
2
4
 
3
5
  class FormNotMultipart < UploadError
@@ -23,9 +25,9 @@ module CarrierWave
23
25
  #
24
26
  def self.generate_cache_id
25
27
  [Time.now.utc.to_i,
26
- Process.pid,
27
- '%04d' % (CarrierWave::CacheCounter.increment % 1000),
28
- '%04d' % rand(9999)
28
+ SecureRandom.random_number(1_000_000_000_000_000),
29
+ '%04d' % (CarrierWave::CacheCounter.increment % 10_000),
30
+ '%04d' % SecureRandom.random_number(10_000)
29
31
  ].map(&:to_s).join('-')
30
32
  end
31
33
 
@@ -36,6 +38,16 @@ module CarrierWave
36
38
  include CarrierWave::Uploader::Callbacks
37
39
  include CarrierWave::Uploader::Configuration
38
40
 
41
+ included do
42
+ prepend Module.new {
43
+ def initialize(*)
44
+ super
45
+ @staged = false
46
+ end
47
+ }
48
+ attr_accessor :staged
49
+ end
50
+
39
51
  module ClassMethods
40
52
 
41
53
  ##
@@ -52,7 +64,7 @@ module CarrierWave
52
64
  # It's recommended that you keep cache files in one place only.
53
65
  #
54
66
  def clean_cached_files!(seconds=60*60*24)
55
- cache_storage.new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
67
+ (cache_storage || storage).new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
56
68
  end
57
69
  end
58
70
 
@@ -78,14 +90,8 @@ module CarrierWave
78
90
  end
79
91
 
80
92
  def sanitized_file
81
- _content = file.read
82
- if _content.is_a?(File) # could be if storage is Fog
83
- sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
84
- else
85
- sanitized = SanitizedFile.new :tempfile => StringIO.new(_content),
86
- :filename => File.basename(path), :content_type => file.content_type
87
- end
88
- sanitized
93
+ ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
94
+ file
89
95
  end
90
96
 
91
97
  ##
@@ -96,7 +102,7 @@ module CarrierWave
96
102
  # [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
97
103
  #
98
104
  def cache_name
99
- File.join(cache_id, full_original_filename) if cache_id and original_filename
105
+ File.join(cache_id, full_original_filename) if cache_id && original_filename
100
106
  end
101
107
 
102
108
  ##
@@ -115,7 +121,7 @@ module CarrierWave
115
121
  #
116
122
  # [CarrierWave::FormNotMultipart] if the assigned parameter is a string
117
123
  #
118
- def cache!(new_file = sanitized_file)
124
+ def cache!(new_file = file)
119
125
  new_file = CarrierWave::SanitizedFile.new(new_file)
120
126
  return if new_file.empty?
121
127
 
@@ -123,6 +129,7 @@ module CarrierWave
123
129
 
124
130
  self.cache_id = CarrierWave.generate_cache_id unless cache_id
125
131
 
132
+ @staged = true
126
133
  @filename = new_file.filename
127
134
  self.original_filename = new_file.filename
128
135
 
@@ -156,6 +163,7 @@ module CarrierWave
156
163
  def retrieve_from_cache!(cache_name)
157
164
  with_callbacks(:retrieve_from_cache, cache_name) do
158
165
  self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
166
+ @staged = true
159
167
  @filename = original_filename
160
168
  @file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
161
169
  end
@@ -200,7 +208,7 @@ module CarrierWave
200
208
  end
201
209
 
202
210
  def cache_storage
203
- @cache_storage ||= self.class.cache_storage.new(self)
211
+ @cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
204
212
  end
205
213
  end # Cache
206
214
  end # Uploader