carrierwave 0.11.2 → 1.3.2

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 (58) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +255 -125
  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 +50 -21
  9. data/lib/carrierwave/processing/mini_magick.rb +86 -15
  10. data/lib/carrierwave/processing/rmagick.rb +63 -8
  11. data/lib/carrierwave/processing.rb +0 -1
  12. data/lib/carrierwave/sanitized_file.rb +51 -46
  13. data/lib/carrierwave/storage/abstract.rb +15 -2
  14. data/lib/carrierwave/storage/file.rb +69 -2
  15. data/lib/carrierwave/storage/fog.rb +152 -33
  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 +54 -9
  21. data/lib/carrierwave/uploader/content_type_whitelist.rb +1 -1
  22. data/lib/carrierwave/uploader/default_url.rb +3 -5
  23. data/lib/carrierwave/uploader/download.rb +66 -15
  24. data/lib/carrierwave/uploader/extension_blacklist.rb +14 -10
  25. data/lib/carrierwave/uploader/extension_whitelist.rb +13 -10
  26. data/lib/carrierwave/uploader/file_size.rb +43 -0
  27. data/lib/carrierwave/uploader/mountable.rb +7 -8
  28. data/lib/carrierwave/uploader/processing.rb +10 -10
  29. data/lib/carrierwave/uploader/proxy.rb +5 -7
  30. data/lib/carrierwave/uploader/remove.rb +0 -2
  31. data/lib/carrierwave/uploader/serialization.rb +1 -3
  32. data/lib/carrierwave/uploader/store.rb +14 -23
  33. data/lib/carrierwave/uploader/url.rb +3 -5
  34. data/lib/carrierwave/uploader/versions.rb +82 -82
  35. data/lib/carrierwave/uploader.rb +11 -2
  36. data/lib/carrierwave/utilities/uri.rb +5 -6
  37. data/lib/carrierwave/utilities.rb +0 -3
  38. data/lib/carrierwave/validations/active_model.rb +3 -5
  39. data/lib/carrierwave/version.rb +1 -1
  40. data/lib/carrierwave.rb +32 -10
  41. data/lib/generators/templates/uploader.rb +4 -8
  42. metadata +64 -79
  43. data/lib/carrierwave/locale/cs.yml +0 -11
  44. data/lib/carrierwave/locale/de.yml +0 -11
  45. data/lib/carrierwave/locale/el.yml +0 -11
  46. data/lib/carrierwave/locale/es.yml +0 -11
  47. data/lib/carrierwave/locale/fr.yml +0 -11
  48. data/lib/carrierwave/locale/ja.yml +0 -11
  49. data/lib/carrierwave/locale/nb.yml +0 -11
  50. data/lib/carrierwave/locale/nl.yml +0 -11
  51. data/lib/carrierwave/locale/pl.yml +0 -11
  52. data/lib/carrierwave/locale/pt-BR.yml +0 -11
  53. data/lib/carrierwave/locale/pt-PT.yml +0 -11
  54. data/lib/carrierwave/locale/ru.yml +0 -11
  55. data/lib/carrierwave/locale/sk.yml +0 -11
  56. data/lib/carrierwave/locale/tr.yml +0 -11
  57. data/lib/carrierwave/processing/mime_types.rb +0 -74
  58. 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
- send(:"\#{column}_will_change!")
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
@@ -62,6 +61,13 @@ module CarrierWave
62
61
  e.message << " (You may need to install the mini_magick gem)"
63
62
  raise e
64
63
  end
64
+
65
+ prepend Module.new {
66
+ def initialize(*)
67
+ super
68
+ @format = nil
69
+ end
70
+ }
65
71
  end
66
72
 
67
73
  module ClassMethods
@@ -81,7 +87,7 @@ module CarrierWave
81
87
  process :resize_to_fill => [width, height, gravity]
82
88
  end
83
89
 
84
- def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
90
+ def resize_and_pad(width, height, background=:transparent, gravity='Center')
85
91
  process :resize_and_pad => [width, height, background, gravity]
86
92
  end
87
93
  end
@@ -103,10 +109,10 @@ module CarrierWave
103
109
  #
104
110
  # image.convert(:png)
105
111
  #
106
- def convert(format)
112
+ def convert(format, page=nil)
107
113
  @format = format
114
+ @page = page
108
115
  manipulate! do |img|
109
- img.format(format.to_s.downcase)
110
116
  img = yield(img) if block_given?
111
117
  img
112
118
  end
@@ -127,9 +133,14 @@ module CarrierWave
127
133
  #
128
134
  # [MiniMagick::Image] additional manipulations to perform
129
135
  #
130
- def resize_to_limit(width, height)
136
+ def resize_to_limit(width, height, combine_options: {})
137
+ width = dimension_from width
138
+ height = dimension_from height
131
139
  manipulate! do |img|
132
- img.resize "#{width}x#{height}>"
140
+ img.combine_options do |cmd|
141
+ cmd.resize "#{width}x#{height}>"
142
+ append_combine_options cmd, combine_options
143
+ end
133
144
  img = yield(img) if block_given?
134
145
  img
135
146
  end
@@ -149,9 +160,14 @@ module CarrierWave
149
160
  #
150
161
  # [MiniMagick::Image] additional manipulations to perform
151
162
  #
152
- def resize_to_fit(width, height)
163
+ def resize_to_fit(width, height, combine_options: {})
164
+ width = dimension_from width
165
+ height = dimension_from height
153
166
  manipulate! do |img|
154
- img.resize "#{width}x#{height}"
167
+ img.combine_options do |cmd|
168
+ cmd.resize "#{width}x#{height}"
169
+ append_combine_options cmd, combine_options
170
+ end
155
171
  img = yield(img) if block_given?
156
172
  img
157
173
  end
@@ -172,7 +188,9 @@ module CarrierWave
172
188
  #
173
189
  # [MiniMagick::Image] additional manipulations to perform
174
190
  #
175
- def resize_to_fill(width, height, gravity = 'Center')
191
+ def resize_to_fill(width, height, gravity = 'Center', combine_options: {})
192
+ width = dimension_from width
193
+ height = dimension_from height
176
194
  manipulate! do |img|
177
195
  cols, rows = img[:dimensions]
178
196
  img.combine_options do |cmd|
@@ -192,6 +210,7 @@ module CarrierWave
192
210
  cmd.gravity gravity
193
211
  cmd.background "rgba(255,255,255,0.0)"
194
212
  cmd.extent "#{width}x#{height}" if cols != width || rows != height
213
+ append_combine_options cmd, combine_options
195
214
  end
196
215
  img = yield(img) if block_given?
197
216
  img
@@ -218,7 +237,9 @@ module CarrierWave
218
237
  #
219
238
  # [MiniMagick::Image] additional manipulations to perform
220
239
  #
221
- def resize_and_pad(width, height, background=:transparent, gravity='Center')
240
+ def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {})
241
+ width = dimension_from width
242
+ height = dimension_from height
222
243
  manipulate! do |img|
223
244
  img.combine_options do |cmd|
224
245
  cmd.thumbnail "#{width}x#{height}>"
@@ -229,12 +250,35 @@ module CarrierWave
229
250
  end
230
251
  cmd.gravity gravity
231
252
  cmd.extent "#{width}x#{height}"
253
+ append_combine_options cmd, combine_options
232
254
  end
233
255
  img = yield(img) if block_given?
234
256
  img
235
257
  end
236
258
  end
237
259
 
260
+ ##
261
+ # Returns the width of the image in pixels.
262
+ #
263
+ # === Returns
264
+ #
265
+ # [Integer] the image's width in pixels
266
+ #
267
+ def width
268
+ mini_magick_image[:width]
269
+ end
270
+
271
+ ##
272
+ # Returns the height of the image in pixels.
273
+ #
274
+ # === Returns
275
+ #
276
+ # [Integer] the image's height in pixels
277
+ #
278
+ def height
279
+ mini_magick_image[:height]
280
+ end
281
+
238
282
  ##
239
283
  # Manipulate the image with MiniMagick. This method will load up an image
240
284
  # and then pass each of its frames to the supplied block. It will then
@@ -260,18 +304,45 @@ module CarrierWave
260
304
  image = ::MiniMagick::Image.open(current_path)
261
305
 
262
306
  begin
263
- image.format(@format.to_s.downcase) if @format
307
+ image.format(@format.to_s.downcase, @page) if @format
264
308
  image = yield(image)
265
309
  image.write(current_path)
310
+
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
316
+
266
317
  image.run_command("identify", current_path)
267
318
  ensure
268
319
  image.destroy!
269
320
  end
270
321
  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)
322
+ message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e)
273
323
  raise CarrierWave::ProcessingError, message
274
324
  end
275
325
 
326
+ private
327
+
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
335
+ end
336
+ end
337
+
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
+ def mini_magick_image
344
+ ::MiniMagick::Image.read(read)
345
+ end
346
+
276
347
  end # MiniMagick
277
348
  end # CarrierWave
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module CarrierWave
4
2
 
5
3
  ##
@@ -69,6 +67,13 @@ module CarrierWave
69
67
  e.message << " (You may need to install the rmagick gem)"
70
68
  raise e
71
69
  end
70
+
71
+ prepend Module.new {
72
+ def initialize(*)
73
+ super
74
+ @format = nil
75
+ end
76
+ }
72
77
  end
73
78
 
74
79
  module ClassMethods
@@ -135,6 +140,8 @@ module CarrierWave
135
140
  # [Magick::Image] additional manipulations to perform
136
141
  #
137
142
  def resize_to_limit(width, height)
143
+ width = dimension_from width
144
+ height = dimension_from height
138
145
  manipulate! do |img|
139
146
  geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
140
147
  new_img = img.change_geometry(geometry) do |new_width, new_height|
@@ -164,6 +171,8 @@ module CarrierWave
164
171
  # [Magick::Image] additional manipulations to perform
165
172
  #
166
173
  def resize_to_fit(width, height)
174
+ width = dimension_from width
175
+ height = dimension_from height
167
176
  manipulate! do |img|
168
177
  img.resize_to_fit!(width, height)
169
178
  img = yield(img) if block_given?
@@ -188,6 +197,8 @@ module CarrierWave
188
197
  # [Magick::Image] additional manipulations to perform
189
198
  #
190
199
  def resize_to_fill(width, height, gravity=::Magick::CenterGravity)
200
+ width = dimension_from width
201
+ height = dimension_from height
191
202
  manipulate! do |img|
192
203
  img.crop_resized!(width, height, gravity)
193
204
  img = yield(img) if block_given?
@@ -213,6 +224,8 @@ module CarrierWave
213
224
  # [Magick::Image] additional manipulations to perform
214
225
  #
215
226
  def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
227
+ width = dimension_from width
228
+ height = dimension_from height
216
229
  manipulate! do |img|
217
230
  img.resize_to_fit!(width, height)
218
231
  new_img = ::Magick::Image.new(width, height) { self.background_color = background == :transparent ? 'rgba(255,255,255,0)' : background.to_s }
@@ -251,6 +264,28 @@ module CarrierWave
251
264
  end
252
265
  end
253
266
 
267
+ ##
268
+ # Returns the width of the image.
269
+ #
270
+ # === Returns
271
+ #
272
+ # [Integer] the image's width in pixels
273
+ #
274
+ def width
275
+ rmagick_image.columns
276
+ end
277
+
278
+ ##
279
+ # Returns the height of the image.
280
+ #
281
+ # === Returns
282
+ #
283
+ # [Integer] the image's height in pixels
284
+ #
285
+ def height
286
+ rmagick_image.rows
287
+ end
288
+
254
289
  ##
255
290
  # Manipulate the image with RMagick. This method will load up an image
256
291
  # and then pass each of its frames to the supplied block. It will then
@@ -318,33 +353,53 @@ module CarrierWave
318
353
  frames = ::Magick::ImageList.new
319
354
 
320
355
  image.each_with_index do |frame, index|
321
- frame = yield *[frame, index, options].take(block.arity) if block_given?
356
+ frame = yield(*[frame, index, options].take(block.arity)) if block_given?
322
357
  frames << frame if frame
323
358
  end
324
359
  frames.append(true) if block_given?
325
360
 
326
361
  write_block = create_info_block(options[:write])
362
+
327
363
  if options[:format] || @format
328
364
  frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
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
367
+ file.move_to(move_to, permissions, directory_permissions)
329
368
  else
330
369
  frames.write(current_path, &write_block)
331
370
  end
371
+
332
372
  destroy_image(frames)
333
373
  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))
374
+ raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e)
335
375
  end
336
376
 
337
377
  private
338
378
 
339
379
  def create_info_block(options)
340
380
  return nil unless options
341
- assignments = options.map { |k, v| "self.#{k} = #{v}" }
342
- code = "lambda { |img| " + assignments.join(";") + "}"
343
- eval code
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
344
390
  end
345
391
 
346
392
  def destroy_image(image)
347
- image.destroy! if image.respond_to?(:destroy!)
393
+ image.try(:destroy!)
394
+ end
395
+
396
+ def dimension_from(value)
397
+ return value unless value.instance_of?(Proc)
398
+ value.arity >= 1 ? value.call(self) : value.call
399
+ end
400
+
401
+ def rmagick_image
402
+ ::Magick::Image.from_blob(self.read).first
348
403
  end
349
404
 
350
405
  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
 
@@ -17,18 +20,19 @@ module CarrierWave
17
20
  #
18
21
  class SanitizedFile
19
22
 
20
- attr_accessor :file
23
+ attr_reader :file
21
24
 
22
25
  class << self
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
 
30
33
  def initialize(file)
31
34
  self.file = file
35
+ @content = nil
32
36
  end
33
37
 
34
38
  ##
@@ -110,12 +114,11 @@ module CarrierWave
110
114
  # [String, nil] the path where the file is located.
111
115
  #
112
116
  def path
113
- unless @file.blank?
114
- if is_path?
115
- File.expand_path(@file)
116
- elsif @file.respond_to?(:path) and not @file.path.blank?
117
- File.expand_path(@file.path)
118
- end
117
+ return if @file.blank?
118
+ if is_path?
119
+ File.expand_path(@file)
120
+ elsif @file.respond_to?(:path) && !@file.path.blank?
121
+ File.expand_path(@file.path)
119
122
  end
120
123
  end
121
124
 
@@ -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
- FileUtils.mv(path, new_path) unless new_path == path
200
+ FileUtils.mv(path, new_path) unless File.identical?(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