carrierwave 0.11.2 → 1.1.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.

Potentially problematic release.


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

Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +223 -116
  3. data/lib/carrierwave/compatibility/paperclip.rb +0 -2
  4. data/lib/carrierwave/error.rb +1 -0
  5. data/lib/carrierwave/locale/en.yml +7 -4
  6. data/lib/carrierwave/mount.rb +219 -176
  7. data/lib/carrierwave/mounter.rb +165 -0
  8. data/lib/carrierwave/orm/activerecord.rb +49 -20
  9. data/lib/carrierwave/processing/mini_magick.rb +69 -15
  10. data/lib/carrierwave/processing/rmagick.rb +32 -4
  11. data/lib/carrierwave/processing.rb +0 -1
  12. data/lib/carrierwave/sanitized_file.rb +43 -38
  13. data/lib/carrierwave/storage/abstract.rb +15 -2
  14. data/lib/carrierwave/storage/file.rb +65 -2
  15. data/lib/carrierwave/storage/fog.rb +105 -28
  16. data/lib/carrierwave/storage.rb +0 -9
  17. data/lib/carrierwave/test/matchers.rb +77 -12
  18. data/lib/carrierwave/uploader/cache.rb +41 -27
  19. data/lib/carrierwave/uploader/callbacks.rb +0 -2
  20. data/lib/carrierwave/uploader/configuration.rb +50 -7
  21. data/lib/carrierwave/uploader/default_url.rb +3 -5
  22. data/lib/carrierwave/uploader/download.rb +10 -7
  23. data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
  24. data/lib/carrierwave/uploader/extension_whitelist.rb +12 -10
  25. data/lib/carrierwave/uploader/file_size.rb +41 -0
  26. data/lib/carrierwave/uploader/magic_mime_blacklist.rb +94 -0
  27. data/lib/carrierwave/uploader/magic_mime_whitelist.rb +94 -0
  28. data/lib/carrierwave/uploader/mountable.rb +7 -8
  29. data/lib/carrierwave/uploader/processing.rb +10 -10
  30. data/lib/carrierwave/uploader/proxy.rb +5 -7
  31. data/lib/carrierwave/uploader/remove.rb +0 -2
  32. data/lib/carrierwave/uploader/serialization.rb +1 -3
  33. data/lib/carrierwave/uploader/store.rb +5 -23
  34. data/lib/carrierwave/uploader/url.rb +3 -5
  35. data/lib/carrierwave/uploader/versions.rb +75 -82
  36. data/lib/carrierwave/uploader.rb +2 -2
  37. data/lib/carrierwave/utilities/uri.rb +4 -7
  38. data/lib/carrierwave/utilities.rb +0 -3
  39. data/lib/carrierwave/validations/active_model.rb +0 -2
  40. data/lib/carrierwave/version.rb +1 -1
  41. data/lib/carrierwave.rb +8 -10
  42. data/lib/generators/templates/uploader.rb +4 -6
  43. metadata +41 -95
  44. data/lib/carrierwave/locale/cs.yml +0 -11
  45. data/lib/carrierwave/locale/de.yml +0 -11
  46. data/lib/carrierwave/locale/el.yml +0 -11
  47. data/lib/carrierwave/locale/es.yml +0 -11
  48. data/lib/carrierwave/locale/fr.yml +0 -11
  49. data/lib/carrierwave/locale/ja.yml +0 -11
  50. data/lib/carrierwave/locale/nb.yml +0 -11
  51. data/lib/carrierwave/locale/nl.yml +0 -11
  52. data/lib/carrierwave/locale/pl.yml +0 -11
  53. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  54. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  55. data/lib/carrierwave/locale/ru.yml +0 -11
  56. data/lib/carrierwave/locale/sk.yml +0 -11
  57. data/lib/carrierwave/locale/tr.yml +0 -11
  58. data/lib/carrierwave/processing/mime_types.rb +0 -74
  59. data/lib/carrierwave/utilities/deprecation.rb +0 -18
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'active_record'
4
2
  require 'carrierwave/validations/active_model'
5
3
 
@@ -14,6 +12,35 @@ module CarrierWave
14
12
  def mount_uploader(column, uploader=nil, options={}, &block)
15
13
  super
16
14
 
15
+ class_eval <<-RUBY, __FILE__, __LINE__+1
16
+ def remote_#{column}_url=(url)
17
+ column = _mounter(:#{column}).serialization_column
18
+ send(:"\#{column}_will_change!")
19
+ super
20
+ end
21
+ RUBY
22
+ end
23
+
24
+ ##
25
+ # See +CarrierWave::Mount#mount_uploaders+ for documentation
26
+ #
27
+ def mount_uploaders(column, uploader=nil, options={}, &block)
28
+ super
29
+
30
+ class_eval <<-RUBY, __FILE__, __LINE__+1
31
+ def remote_#{column}_urls=(url)
32
+ column = _mounter(:#{column}).serialization_column
33
+ send(:"\#{column}_will_change!")
34
+ super
35
+ end
36
+ RUBY
37
+ end
38
+
39
+ private
40
+
41
+ def mount_base(column, uploader=nil, options={}, &block)
42
+ super
43
+
17
44
  alias_method :read_uploader, :read_attribute
18
45
  alias_method :write_uploader, :write_attribute
19
46
  public :read_uploader
@@ -29,43 +56,45 @@ module CarrierWave
29
56
  before_save :"write_#{column}_identifier"
30
57
  after_commit :"remove_#{column}!", :on => :destroy
31
58
  after_commit :"mark_remove_#{column}_false", :on => :update
32
- before_update :"store_previous_model_for_#{column}"
33
- after_save :"remove_previously_stored_#{column}"
59
+
60
+ after_save :"store_previous_changes_for_#{column}"
61
+ after_commit :"remove_previously_stored_#{column}", :on => :update
34
62
 
35
63
  class_eval <<-RUBY, __FILE__, __LINE__+1
36
64
  def #{column}=(new_file)
37
65
  column = _mounter(:#{column}).serialization_column
38
- send(:"\#{column}_will_change!")
66
+ if !(new_file.blank? && send(:#{column}).blank?)
67
+ send(:"\#{column}_will_change!")
68
+ end
69
+
39
70
  super
40
71
  end
41
72
 
42
- def remote_#{column}_url=(url)
73
+ def remove_#{column}=(value)
43
74
  column = _mounter(:#{column}).serialization_column
44
75
  send(:"\#{column}_will_change!")
45
76
  super
46
77
  end
47
78
 
48
79
  def remove_#{column}!
80
+ self.remove_#{column} = true
81
+ write_#{column}_identifier
82
+ self.remove_#{column} = false
49
83
  super
50
- _mounter(:#{column}).remove = true
51
- _mounter(:#{column}).write_identifier
52
84
  end
53
85
 
54
- def serializable_hash(options=nil)
55
- hash = {}
56
-
57
- except = options && options[:except] && Array.wrap(options[:except]).map(&:to_s)
58
- only = options && options[:only] && Array.wrap(options[:only]).map(&:to_s)
86
+ # Reset cached mounter on record reload
87
+ def reload(*)
88
+ @_mounters = nil
89
+ super
90
+ end
59
91
 
60
- self.class.uploaders.each do |column, uploader|
61
- if (!only && !except) || (only && only.include?(column.to_s)) || (!only && except && !except.include?(column.to_s))
62
- hash[column.to_s] = _mounter(column).uploader.serializable_hash
63
- end
64
- end
65
- super(options).merge(hash)
92
+ # Reset cached mounter on record dup
93
+ def initialize_dup(other)
94
+ @_mounters = nil
95
+ super
66
96
  end
67
97
  RUBY
68
-
69
98
  end
70
99
 
71
100
  end # ActiveRecord
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
 
5
3
  ##
@@ -39,6 +37,7 @@ module CarrierWave
39
37
  # img
40
38
  # end
41
39
  # end
40
+ # end
42
41
  #
43
42
  # === Note
44
43
  #
@@ -49,7 +48,7 @@ module CarrierWave
49
48
  #
50
49
  # http://mini_magick.rubyforge.org/
51
50
  # and
52
- # https://github.com/minimagic/minimagick/
51
+ # https://github.com/minimagick/minimagick/
53
52
  #
54
53
  #
55
54
  module MiniMagick
@@ -81,7 +80,7 @@ module CarrierWave
81
80
  process :resize_to_fill => [width, height, gravity]
82
81
  end
83
82
 
84
- def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
83
+ def resize_and_pad(width, height, background=:transparent, gravity='Center')
85
84
  process :resize_and_pad => [width, height, background, gravity]
86
85
  end
87
86
  end
@@ -103,10 +102,10 @@ module CarrierWave
103
102
  #
104
103
  # image.convert(:png)
105
104
  #
106
- def convert(format)
105
+ def convert(format, page=nil)
107
106
  @format = format
107
+ @page = page
108
108
  manipulate! do |img|
109
- img.format(format.to_s.downcase)
110
109
  img = yield(img) if block_given?
111
110
  img
112
111
  end
@@ -127,9 +126,12 @@ module CarrierWave
127
126
  #
128
127
  # [MiniMagick::Image] additional manipulations to perform
129
128
  #
130
- def resize_to_limit(width, height)
129
+ def resize_to_limit(width, height, combine_options: {})
131
130
  manipulate! do |img|
132
- img.resize "#{width}x#{height}>"
131
+ img.combine_options do |cmd|
132
+ cmd.resize "#{width}x#{height}>"
133
+ append_combine_options cmd, combine_options
134
+ end
133
135
  img = yield(img) if block_given?
134
136
  img
135
137
  end
@@ -149,9 +151,12 @@ module CarrierWave
149
151
  #
150
152
  # [MiniMagick::Image] additional manipulations to perform
151
153
  #
152
- def resize_to_fit(width, height)
154
+ def resize_to_fit(width, height, combine_options: {})
153
155
  manipulate! do |img|
154
- img.resize "#{width}x#{height}"
156
+ img.combine_options do |cmd|
157
+ cmd.resize "#{width}x#{height}"
158
+ append_combine_options cmd, combine_options
159
+ end
155
160
  img = yield(img) if block_given?
156
161
  img
157
162
  end
@@ -172,7 +177,7 @@ module CarrierWave
172
177
  #
173
178
  # [MiniMagick::Image] additional manipulations to perform
174
179
  #
175
- def resize_to_fill(width, height, gravity = 'Center')
180
+ def resize_to_fill(width, height, gravity = 'Center', combine_options: {})
176
181
  manipulate! do |img|
177
182
  cols, rows = img[:dimensions]
178
183
  img.combine_options do |cmd|
@@ -192,6 +197,7 @@ module CarrierWave
192
197
  cmd.gravity gravity
193
198
  cmd.background "rgba(255,255,255,0.0)"
194
199
  cmd.extent "#{width}x#{height}" if cols != width || rows != height
200
+ append_combine_options cmd, combine_options
195
201
  end
196
202
  img = yield(img) if block_given?
197
203
  img
@@ -218,7 +224,7 @@ module CarrierWave
218
224
  #
219
225
  # [MiniMagick::Image] additional manipulations to perform
220
226
  #
221
- def resize_and_pad(width, height, background=:transparent, gravity='Center')
227
+ def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {})
222
228
  manipulate! do |img|
223
229
  img.combine_options do |cmd|
224
230
  cmd.thumbnail "#{width}x#{height}>"
@@ -229,12 +235,35 @@ module CarrierWave
229
235
  end
230
236
  cmd.gravity gravity
231
237
  cmd.extent "#{width}x#{height}"
238
+ append_combine_options cmd, combine_options
232
239
  end
233
240
  img = yield(img) if block_given?
234
241
  img
235
242
  end
236
243
  end
237
244
 
245
+ ##
246
+ # Returns the width of the image in pixels.
247
+ #
248
+ # === Returns
249
+ #
250
+ # [Integer] the image's width in pixels
251
+ #
252
+ def width
253
+ mini_magick_image[:width]
254
+ end
255
+
256
+ ##
257
+ # Returns the height of the image in pixels.
258
+ #
259
+ # === Returns
260
+ #
261
+ # [Integer] the image's height in pixels
262
+ #
263
+ def height
264
+ mini_magick_image[:height]
265
+ end
266
+
238
267
  ##
239
268
  # Manipulate the image with MiniMagick. This method will load up an image
240
269
  # and then pass each of its frames to the supplied block. It will then
@@ -260,18 +289,43 @@ module CarrierWave
260
289
  image = ::MiniMagick::Image.open(current_path)
261
290
 
262
291
  begin
263
- image.format(@format.to_s.downcase) if @format
292
+ image.format(@format.to_s.downcase, @page) if @format
264
293
  image = yield(image)
265
294
  image.write(current_path)
295
+
296
+ if @format
297
+ move_to = current_path.chomp(File.extname(current_path)) + ".#{@format}"
298
+ file.move_to(move_to, permissions, directory_permissions)
299
+ end
300
+
266
301
  image.run_command("identify", current_path)
267
302
  ensure
268
303
  image.destroy!
269
304
  end
270
305
  rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
271
- default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
272
- message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
306
+ message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e)
273
307
  raise CarrierWave::ProcessingError, message
274
308
  end
275
309
 
310
+ private
311
+
312
+ def append_combine_options(cmd, combine_options)
313
+ combine_options.each do |method, options|
314
+ if options.nil?
315
+ cmd.send(method)
316
+ else
317
+ cmd.send(method, options)
318
+ end
319
+ end
320
+ end
321
+
322
+ def mini_magick_image
323
+ if url
324
+ ::MiniMagick::Image.open(url)
325
+ else
326
+ ::MiniMagick::Image.open(current_path)
327
+ end
328
+ end
329
+
276
330
  end # MiniMagick
277
331
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
 
5
3
  ##
@@ -251,6 +249,28 @@ module CarrierWave
251
249
  end
252
250
  end
253
251
 
252
+ ##
253
+ # Returns the width of the image.
254
+ #
255
+ # === Returns
256
+ #
257
+ # [Integer] the image's width in pixels
258
+ #
259
+ def width
260
+ rmagick_image.columns
261
+ end
262
+
263
+ ##
264
+ # Returns the height of the image.
265
+ #
266
+ # === Returns
267
+ #
268
+ # [Integer] the image's height in pixels
269
+ #
270
+ def height
271
+ rmagick_image.rows
272
+ end
273
+
254
274
  ##
255
275
  # Manipulate the image with RMagick. This method will load up an image
256
276
  # and then pass each of its frames to the supplied block. It will then
@@ -324,14 +344,18 @@ module CarrierWave
324
344
  frames.append(true) if block_given?
325
345
 
326
346
  write_block = create_info_block(options[:write])
347
+
327
348
  if options[:format] || @format
328
349
  frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
350
+ move_to = current_path.chomp(File.extname(current_path)) + ".#{options[:format] || @format}"
351
+ file.move_to(move_to, permissions, directory_permissions)
329
352
  else
330
353
  frames.write(current_path, &write_block)
331
354
  end
355
+
332
356
  destroy_image(frames)
333
357
  rescue ::Magick::ImageMagickError => e
334
- raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e, :default => I18n.translate(:"errors.messages.rmagick_processing_error", :e => e, :locale => :en))
358
+ raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e)
335
359
  end
336
360
 
337
361
  private
@@ -344,7 +368,11 @@ module CarrierWave
344
368
  end
345
369
 
346
370
  def destroy_image(image)
347
- image.destroy! if image.respond_to?(:destroy!)
371
+ image.try(:destroy!)
372
+ end
373
+
374
+ def rmagick_image
375
+ ::Magick::Image.read(current_path).first
348
376
  end
349
377
 
350
378
  end # RMagick
@@ -1,3 +1,2 @@
1
1
  require "carrierwave/processing/rmagick"
2
2
  require "carrierwave/processing/mini_magick"
3
- require "carrierwave/processing/mime_types"
@@ -1,9 +1,12 @@
1
- # encoding: utf-8
2
-
3
1
  require 'pathname'
4
2
  require 'active_support/core_ext/string/multibyte'
5
- require 'mime/types'
6
- require 'mimemagic'
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
7
10
 
8
11
  module CarrierWave
9
12
 
@@ -23,7 +26,7 @@ module CarrierWave
23
26
  attr_writer :sanitize_regexp
24
27
 
25
28
  def sanitize_regexp
26
- @sanitize_regexp ||= /[^a-zA-Z0-9\.\-\+_]/
29
+ @sanitize_regexp ||= /[^[:word:]\.\-\+]/
27
30
  end
28
31
  end
29
32
 
@@ -143,8 +146,7 @@ module CarrierWave
143
146
  # [Boolean] Whether the file exists
144
147
  #
145
148
  def exists?
146
- return File.exists?(self.path) if self.path
147
- return false
149
+ self.path.present? && File.exist?(self.path)
148
150
  end
149
151
 
150
152
  ##
@@ -160,9 +162,9 @@ module CarrierWave
160
162
  elsif is_path?
161
163
  File.open(@file, "rb") {|file| file.read}
162
164
  else
163
- @file.rewind if @file.respond_to?(:rewind)
165
+ @file.try(:rewind)
164
166
  @content = @file.read
165
- @file.close if @file.respond_to?(:close) && @file.respond_to?(:closed?) && !@file.closed?
167
+ @file.try(:close) unless @file.try(:closed?)
166
168
  @content
167
169
  end
168
170
  end
@@ -176,19 +178,29 @@ module CarrierWave
176
178
  # [permissions (Integer)] permissions to set on the file in its new location.
177
179
  # [directory_permissions (Integer)] permissions to set on created directories.
178
180
  #
179
- def move_to(new_path, permissions=nil, directory_permissions=nil)
181
+ def move_to(new_path, permissions=nil, directory_permissions=nil, keep_filename=false)
180
182
  return if self.empty?
181
183
  new_path = File.expand_path(new_path)
182
184
 
183
185
  mkdir!(new_path, directory_permissions)
186
+ move!(new_path)
187
+ chmod!(new_path, permissions)
188
+ if keep_filename
189
+ self.file = {:tempfile => new_path, :filename => original_filename, :content_type => content_type}
190
+ else
191
+ self.file = {:tempfile => new_path, :content_type => content_type}
192
+ end
193
+ self
194
+ end
195
+ ##
196
+ # Helper to move file to new path.
197
+ #
198
+ def move!(new_path)
184
199
  if exists?
185
200
  FileUtils.mv(path, new_path) unless new_path == path
186
201
  else
187
202
  File.open(new_path, "wb") { |f| f.write(read) }
188
203
  end
189
- chmod!(new_path, permissions)
190
- self.file = new_path
191
- self
192
204
  end
193
205
 
194
206
  ##
@@ -209,13 +221,20 @@ module CarrierWave
209
221
  new_path = File.expand_path(new_path)
210
222
 
211
223
  mkdir!(new_path, directory_permissions)
224
+ copy!(new_path)
225
+ chmod!(new_path, permissions)
226
+ self.class.new({:tempfile => new_path, :content_type => content_type})
227
+ end
228
+
229
+ ##
230
+ # Helper to create copy of file in new path.
231
+ #
232
+ def copy!(new_path)
212
233
  if exists?
213
234
  FileUtils.cp(path, new_path) unless new_path == path
214
235
  else
215
236
  File.open(new_path, "wb") { |f| f.write(read) }
216
237
  end
217
- chmod!(new_path, permissions)
218
- self.class.new({:tempfile => new_path, :content_type => content_type})
219
238
  end
220
239
 
221
240
  ##
@@ -245,10 +264,12 @@ module CarrierWave
245
264
  # [String] the content type of the file
246
265
  #
247
266
  def content_type
248
- @content_type ||=
249
- existing_content_type ||
250
- mime_magic_content_type ||
251
- mime_types_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
252
273
  end
253
274
 
254
275
  ##
@@ -279,7 +300,7 @@ module CarrierWave
279
300
  if file.is_a?(Hash)
280
301
  @file = file["tempfile"] || file[:tempfile]
281
302
  @original_filename = file["filename"] || file[:filename]
282
- @content_type = file["content_type"] || file[:content_type]
303
+ @content_type = file["content_type"] || file[:content_type] || file["type"] || file[:type]
283
304
  else
284
305
  @file = file
285
306
  @original_filename = nil
@@ -291,7 +312,7 @@ module CarrierWave
291
312
  def mkdir!(path, directory_permissions)
292
313
  options = {}
293
314
  options[:mode] = directory_permissions if directory_permissions
294
- FileUtils.mkdir_p(File.dirname(path), options) unless File.exists?(File.dirname(path))
315
+ FileUtils.mkdir_p(File.dirname(path), options) unless File.exist?(File.dirname(path))
295
316
  end
296
317
 
297
318
  def chmod!(path, permissions)
@@ -300,7 +321,7 @@ module CarrierWave
300
321
 
301
322
  # Sanitize the filename, to prevent hacking
302
323
  def sanitize(name)
303
- name = name.gsub("\\", "/") # work-around for IE
324
+ name = name.tr("\\", "/") # work-around for IE
304
325
  name = File.basename(name)
305
326
  name = name.gsub(sanitize_regexp,"_")
306
327
  name = "_#{name}" if name =~ /\A\.+\z/
@@ -308,22 +329,6 @@ module CarrierWave
308
329
  return name.mb_chars.to_s
309
330
  end
310
331
 
311
- def existing_content_type
312
- if @file.respond_to?(:content_type) && @file.content_type
313
- @file.content_type.to_s.chomp
314
- end
315
- end
316
-
317
- def mime_magic_content_type
318
- MimeMagic.by_magic(File.open(path)).try(:type) if path
319
- rescue Errno::ENOENT
320
- nil
321
- end
322
-
323
- def mime_types_content_type
324
- ::MIME::Types.type_for(path).first.to_s if path
325
- end
326
-
327
332
  def split_extension(filename)
328
333
  # regular expressions to try for identifying extensions
329
334
  extension_matchers = [
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Storage
5
3
 
@@ -25,6 +23,21 @@ module CarrierWave
25
23
  def retrieve!(identifier)
26
24
  end
27
25
 
26
+ def cache!(new_file)
27
+ raise NotImplementedError.new("Need to implement #cache! if you want to use #{self.class.name} as a cache storage.")
28
+ end
29
+
30
+ def retrieve_from_cache!(identifier)
31
+ raise NotImplementedError.new("Need to implement #retrieve_from_cache! if you want to use #{self.class.name} as a cache storage.")
32
+ end
33
+
34
+ def delete_dir!(path)
35
+ raise NotImplementedError.new("Need to implement #delete_dir! if you want to use #{self.class.name} as a cache storage.")
36
+ end
37
+
38
+ def clean_cache!(seconds)
39
+ raise NotImplementedError.new("Need to implement #clean_cache! if you want to use #{self.class.name} as a cache storage.")
40
+ end
28
41
  end # Abstract
29
42
  end # Storage
30
43
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
  module Storage
5
3
 
@@ -51,6 +49,71 @@ module CarrierWave
51
49
  CarrierWave::SanitizedFile.new(path)
52
50
  end
53
51
 
52
+ ##
53
+ # Stores given file to cache directory.
54
+ #
55
+ # === Parameters
56
+ #
57
+ # [new_file (File, IOString, Tempfile)] any kind of file object
58
+ #
59
+ # === Returns
60
+ #
61
+ # [CarrierWave::SanitizedFile] a sanitized file
62
+ #
63
+ def cache!(new_file)
64
+ new_file.move_to(::File.expand_path(uploader.cache_path, uploader.root), uploader.permissions, uploader.directory_permissions, true)
65
+ rescue Errno::EMLINK => e
66
+ raise(e) if @cache_called
67
+ @cache_called = true
68
+
69
+ # NOTE: Remove cached files older than 10 minutes
70
+ clean_cache!(600)
71
+
72
+ cache!(new_file)
73
+ end
74
+
75
+ ##
76
+ # Retrieves the file with the given cache_name from the cache.
77
+ #
78
+ # === Parameters
79
+ #
80
+ # [cache_name (String)] uniquely identifies a cache file
81
+ #
82
+ # === Raises
83
+ #
84
+ # [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
85
+ #
86
+ def retrieve_from_cache!(identifier)
87
+ CarrierWave::SanitizedFile.new(::File.expand_path(uploader.cache_path(identifier), uploader.root))
88
+ end
89
+
90
+ ##
91
+ # Deletes a cache dir
92
+ #
93
+ def delete_dir!(path)
94
+ if path
95
+ begin
96
+ Dir.rmdir(::File.expand_path(path, uploader.root))
97
+ rescue Errno::ENOENT
98
+ # Ignore: path does not exist
99
+ rescue Errno::ENOTDIR
100
+ # Ignore: path is not a dir
101
+ rescue Errno::ENOTEMPTY, Errno::EEXIST
102
+ # Ignore: dir is not empty
103
+ end
104
+ end
105
+ end
106
+
107
+ def clean_cache!(seconds)
108
+ Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), CarrierWave.root)).each do |dir|
109
+ # generate_cache_id returns key formated TIMEINT-PID-COUNTER-RND
110
+ time = dir.scan(/(\d+)-\d+-\d+-\d+/).first.map(&:to_i)
111
+ time = Time.at(*time)
112
+ if time < (Time.now.utc - seconds)
113
+ FileUtils.rm_rf(dir)
114
+ end
115
+ end
116
+ end
54
117
  end # File
55
118
  end # Storage
56
119
  end # CarrierWave