carrierwave 3.0.0.beta → 3.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.

Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +104 -64
  3. data/lib/carrierwave/compatibility/paperclip.rb +4 -2
  4. data/lib/carrierwave/downloader/base.rb +12 -11
  5. data/lib/carrierwave/downloader/remote_file.rb +5 -6
  6. data/lib/carrierwave/locale/en.yml +4 -0
  7. data/lib/carrierwave/mount.rb +31 -82
  8. data/lib/carrierwave/mounter.rb +115 -50
  9. data/lib/carrierwave/orm/activerecord.rb +8 -59
  10. data/lib/carrierwave/processing/mini_magick.rb +13 -11
  11. data/lib/carrierwave/processing/rmagick.rb +7 -11
  12. data/lib/carrierwave/processing/vips.rb +9 -9
  13. data/lib/carrierwave/sanitized_file.rb +47 -37
  14. data/lib/carrierwave/storage/abstract.rb +5 -5
  15. data/lib/carrierwave/storage/file.rb +4 -3
  16. data/lib/carrierwave/storage/fog.rb +69 -50
  17. data/lib/carrierwave/test/matchers.rb +11 -7
  18. data/lib/carrierwave/uploader/cache.rb +17 -9
  19. data/lib/carrierwave/uploader/callbacks.rb +1 -1
  20. data/lib/carrierwave/uploader/configuration.rb +8 -4
  21. data/lib/carrierwave/uploader/dimension.rb +66 -0
  22. data/lib/carrierwave/uploader/file_size.rb +2 -2
  23. data/lib/carrierwave/uploader/processing.rb +21 -7
  24. data/lib/carrierwave/uploader/proxy.rb +16 -3
  25. data/lib/carrierwave/uploader/store.rb +43 -6
  26. data/lib/carrierwave/uploader/url.rb +1 -1
  27. data/lib/carrierwave/uploader/versions.rb +126 -134
  28. data/lib/carrierwave/uploader.rb +2 -0
  29. data/lib/carrierwave/utilities/file_name.rb +2 -2
  30. data/lib/carrierwave/utilities/uri.rb +14 -11
  31. data/lib/carrierwave/validations/active_model.rb +4 -6
  32. data/lib/carrierwave/version.rb +1 -1
  33. data/lib/carrierwave.rb +8 -7
  34. data/lib/generators/uploader_generator.rb +3 -3
  35. metadata +18 -3
  36. /data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +0 -0
@@ -162,7 +162,7 @@ module CarrierWave
162
162
  end
163
163
 
164
164
  class File
165
- DEFAULT_S3_REGION = 'us-east-1'
165
+ DEFAULT_S3_REGION = 'us-east-1'.freeze
166
166
 
167
167
  include CarrierWave::Utilities::Uri
168
168
  include CarrierWave::Utilities::FileName
@@ -198,27 +198,27 @@ module CarrierWave
198
198
  # [NilClass] no authenticated url available
199
199
  #
200
200
  def authenticated_url(options = {})
201
- if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(@uploader.fog_credentials[:provider])
201
+ if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(fog_provider)
202
202
  # avoid a get by using local references
203
203
  local_directory = connection.directories.new(:key => @uploader.fog_directory)
204
204
  local_file = local_directory.files.new(:key => path)
205
205
  expire_at = options[:expire_at] || ::Fog::Time.now.since(@uploader.fog_authenticated_url_expiration.to_i)
206
- case @uploader.fog_credentials[:provider]
207
- when 'AWS', 'Google'
208
- # Older versions of fog-google do not support options as a parameter
209
- if url_options_supported?(local_file)
210
- local_file.url(expire_at, options)
211
- else
212
- warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
213
- local_file.url(expire_at)
214
- end
215
- when 'Rackspace', 'OpenStack'
216
- connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
217
- when 'Aliyun'
218
- expire_at = expire_at - Time.now
219
- local_file.url(expire_at)
206
+ case fog_provider
207
+ when 'AWS', 'Google'
208
+ # Older versions of fog-google do not support options as a parameter
209
+ if url_options_supported?(local_file)
210
+ local_file.url(expire_at, options)
220
211
  else
212
+ warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
221
213
  local_file.url(expire_at)
214
+ end
215
+ when 'Rackspace', 'OpenStack'
216
+ connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
217
+ when 'Aliyun'
218
+ expire_at -= Time.now
219
+ local_file.url(expire_at)
220
+ else
221
+ local_file.url(expire_at)
222
222
  end
223
223
  end
224
224
  end
@@ -285,16 +285,16 @@ module CarrierWave
285
285
  #
286
286
  # [String] contents of file
287
287
  def read
288
- file_body = file.body
288
+ file_body = file&.body
289
289
 
290
290
  return if file_body.nil?
291
291
  return file_body unless file_body.is_a?(::File)
292
292
 
293
- # Fog::Storage::XXX::File#body could return the source file which was upoloaded to the remote server.
294
- read_source_file(file_body) if ::File.exist?(file_body.path)
293
+ # Fog::Storage::XXX::File#body could return the source file which was uploaded to the remote server.
294
+ return read_source_file if ::File.exist?(file_body.path)
295
295
 
296
296
  # If the source file doesn't exist, the remote content is read
297
- @file = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
297
+ @file = nil
298
298
  file.body
299
299
  end
300
300
 
@@ -332,7 +332,7 @@ module CarrierWave
332
332
  fog_file = new_file.to_file
333
333
  @content_type ||= new_file.content_type
334
334
  @file = directory.files.create({
335
- :body => fog_file ? fog_file : new_file.read,
335
+ :body => fog_file || new_file.read,
336
336
  :content_type => @content_type,
337
337
  :key => path,
338
338
  :public => @uploader.fog_public
@@ -353,7 +353,7 @@ module CarrierWave
353
353
  #
354
354
  def public_url
355
355
  encoded_path = encode_path(path)
356
- if host = @uploader.asset_host
356
+ if (host = @uploader.asset_host)
357
357
  if host.respond_to? :call
358
358
  "#{host.call(self)}/#{encoded_path}"
359
359
  else
@@ -370,21 +370,22 @@ module CarrierWave
370
370
  protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
371
371
 
372
372
  subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
373
- valid_subdomain = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
374
-
375
- # if directory is a valid subdomain, use that style for access
376
- if valid_subdomain
377
- s3_subdomain = @uploader.fog_aws_accelerate ? "s3-accelerate" : "s3"
378
- "#{protocol}://#{@uploader.fog_directory}.#{s3_subdomain}.amazonaws.com/#{encoded_path}"
373
+ # To use the virtual-hosted style, the bucket name needs to be representable as a subdomain
374
+ use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
375
+
376
+ region = @uploader.fog_credentials[:region].to_s
377
+ regional_host = case region
378
+ when DEFAULT_S3_REGION, ''
379
+ 's3.amazonaws.com'
380
+ else
381
+ "s3.#{region}.amazonaws.com"
382
+ end
383
+
384
+ if use_virtual_hosted_style
385
+ regional_host = 's3-accelerate.amazonaws.com' if @uploader.fog_aws_accelerate
386
+ "#{protocol}://#{@uploader.fog_directory}.#{regional_host}/#{encoded_path}"
379
387
  else # directory is not a valid subdomain, so use path style for access
380
- region = @uploader.fog_credentials[:region].to_s
381
- host = case region
382
- when DEFAULT_S3_REGION, ''
383
- 's3.amazonaws.com'
384
- else
385
- "s3.#{region}.amazonaws.com"
386
- end
387
- "#{protocol}://#{host}/#{@uploader.fog_directory}/#{encoded_path}"
388
+ "#{protocol}://#{regional_host}/#{@uploader.fog_directory}/#{encoded_path}"
388
389
  end
389
390
  end
390
391
  when 'Google'
@@ -424,7 +425,7 @@ module CarrierWave
424
425
  # [NilClass] no file name available
425
426
  #
426
427
  def filename(options = {})
427
- return unless file_url = url(options)
428
+ return unless (file_url = url(options))
428
429
  CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
429
430
  end
430
431
 
@@ -444,6 +445,25 @@ module CarrierWave
444
445
  CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
445
446
  end
446
447
 
448
+ ##
449
+ # Return the local file
450
+ #
451
+ # === Returns
452
+ #
453
+ # [File] The local file as Ruby's File class
454
+ # or
455
+ # [NilClass] When there's no file, or the file is remotely stored
456
+ #
457
+ def to_file
458
+ return nil unless file.body.is_a? ::File
459
+
460
+ if file.body.closed?
461
+ ::File.open(file.body.path) # Reopen if it's already closed
462
+ else
463
+ file.body
464
+ end
465
+ end
466
+
447
467
  private
448
468
 
449
469
  ##
@@ -465,12 +485,10 @@ module CarrierWave
465
485
  # [Fog::#{provider}::Directory] containing directory
466
486
  #
467
487
  def directory
468
- @directory ||= begin
469
- connection.directories.new(
470
- :key => @uploader.fog_directory,
471
- :public => @uploader.fog_public
472
- )
473
- end
488
+ @directory ||= connection.directories.new(
489
+ :key => @uploader.fog_directory,
490
+ :public => @uploader.fog_public
491
+ )
474
492
  end
475
493
 
476
494
  ##
@@ -492,9 +510,10 @@ module CarrierWave
492
510
  end
493
511
 
494
512
  def acl_header
495
- if fog_provider == 'AWS'
513
+ case fog_provider
514
+ when 'AWS'
496
515
  { 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
497
- elsif fog_provider == "Google"
516
+ when "Google"
498
517
  @uploader.fog_public ? { destination_predefined_acl: "publicRead" } : {}
499
518
  else
500
519
  {}
@@ -505,14 +524,14 @@ module CarrierWave
505
524
  @uploader.fog_credentials[:provider].to_s
506
525
  end
507
526
 
508
- def read_source_file(file_body)
509
- return unless ::File.exist?(file_body.path)
527
+ def read_source_file
528
+ source_file = to_file
529
+ return unless source_file
510
530
 
511
531
  begin
512
- file_body = ::File.open(file_body.path) if file_body.closed? # Reopen if it's already closed
513
- file_body.read
532
+ source_file.read
514
533
  ensure
515
- file_body.close
534
+ source_file.close
516
535
  end
517
536
  end
518
537
 
@@ -45,11 +45,11 @@ module CarrierWave
45
45
  def matches?(actual)
46
46
  @actual = actual
47
47
  # Satisfy expectation here. Return false or raise an error if it's not met.
48
- (File.stat(@actual.path).mode & 0777) == @expected
48
+ (File.stat(@actual.path).mode & 0o777) == @expected
49
49
  end
50
50
 
51
51
  def failure_message
52
- "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)}"
53
53
  end
54
54
 
55
55
  def failure_message_when_negated
@@ -76,11 +76,11 @@ module CarrierWave
76
76
  def matches?(actual)
77
77
  @actual = actual
78
78
  # Satisfy expectation here. Return false or raise an error if it's not met.
79
- (File.stat(File.dirname @actual.path).mode & 0777) == @expected
79
+ (File.stat(File.dirname(@actual.path)).mode & 0o777) == @expected
80
80
  end
81
81
 
82
82
  def failure_message
83
- "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)}"
84
84
  end
85
85
 
86
86
  def failure_message_when_negated
@@ -341,9 +341,11 @@ module CarrierWave
341
341
  begin
342
342
  require 'rmagick'
343
343
  rescue LoadError
344
- require 'RMagick'
345
- rescue LoadError
346
- 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
347
349
  end
348
350
  end
349
351
  MagickWrapper.new(filename)
@@ -353,6 +355,7 @@ module CarrierWave
353
355
 
354
356
  class MagickWrapper # :nodoc:
355
357
  attr_reader :image
358
+
356
359
  def width
357
360
  image.columns
358
361
  end
@@ -372,6 +375,7 @@ module CarrierWave
372
375
 
373
376
  class MiniMagickWrapper # :nodoc:
374
377
  attr_reader :image
378
+
375
379
  def width
376
380
  image[:width]
377
381
  end
@@ -24,7 +24,8 @@ 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,
27
+ [
28
+ Time.now.utc.to_i,
28
29
  SecureRandom.random_number(1_000_000_000_000_000),
29
30
  '%04d' % (CarrierWave::CacheCounter.increment % 10_000),
30
31
  '%04d' % SecureRandom.random_number(10_000)
@@ -64,7 +65,7 @@ module CarrierWave
64
65
  # It's recommended that you keep cache files in one place only.
65
66
  #
66
67
  def clean_cached_files!(seconds=60*60*24)
67
- (cache_storage || storage).new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
68
+ (cache_storage || storage).new(new).clean_cache!(seconds)
68
69
  end
69
70
  end
70
71
 
@@ -102,7 +103,7 @@ module CarrierWave
102
103
  # [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
103
104
  #
104
105
  def cache_name
105
- File.join(cache_id, full_original_filename) if cache_id && original_filename
106
+ File.join(cache_id, original_filename) if cache_id && original_filename
106
107
  end
107
108
 
108
109
  ##
@@ -129,6 +130,7 @@ module CarrierWave
129
130
 
130
131
  self.cache_id = CarrierWave.generate_cache_id unless cache_id
131
132
 
133
+ @identifier = nil
132
134
  @staged = true
133
135
  @filename = new_file.filename
134
136
  self.original_filename = new_file.filename
@@ -165,7 +167,7 @@ module CarrierWave
165
167
  self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
166
168
  @staged = true
167
169
  @filename = original_filename
168
- @file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
170
+ @file = cache_storage.retrieve_from_cache!(full_original_filename)
169
171
  end
170
172
  end
171
173
 
@@ -180,20 +182,21 @@ module CarrierWave
180
182
  #
181
183
  # [String] the cache path
182
184
  #
183
- def cache_path(for_file=full_filename(original_filename))
185
+ def cache_path(for_file=full_original_filename)
184
186
  File.join(*[cache_dir, @cache_id, for_file].compact)
185
187
  end
186
188
 
189
+ protected
190
+
191
+ attr_reader :cache_id
192
+
187
193
  private
188
194
 
189
195
  def workfile_path(for_file=original_filename)
190
196
  File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
191
197
  end
192
198
 
193
- attr_reader :cache_id, :original_filename
194
-
195
- # We can override the full_original_filename method in other modules
196
- alias_method :full_original_filename, :original_filename
199
+ attr_reader :original_filename
197
200
 
198
201
  def cache_id=(cache_id)
199
202
  # Earlier version used 3 part cache_id. Thus we should allow for
@@ -210,6 +213,11 @@ module CarrierWave
210
213
  def cache_storage
211
214
  @cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
212
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
213
221
  end # Cache
214
222
  end # Uploader
215
223
  end # CarrierWave
@@ -5,7 +5,7 @@ module CarrierWave
5
5
 
6
6
  included do
7
7
  class_attribute :_before_callbacks, :_after_callbacks,
8
- :instance_writer => false
8
+ :instance_writer => false
9
9
  self._before_callbacks = Hash.new []
10
10
  self._after_callbacks = Hash.new []
11
11
  end
@@ -24,6 +24,7 @@ module CarrierWave
24
24
  add_config :move_to_store
25
25
  add_config :remove_previously_stored_files_after_update
26
26
  add_config :downloader
27
+ add_config :force_extension
27
28
 
28
29
  # fog
29
30
  add_deprecated_config :fog_provider
@@ -45,6 +46,7 @@ module CarrierWave
45
46
  add_config :mount_on
46
47
  add_config :cache_only
47
48
  add_config :download_retry_count
49
+ add_config :download_retry_wait_time
48
50
 
49
51
  # set default values
50
52
  reset_config
@@ -78,7 +80,7 @@ module CarrierWave
78
80
  def storage(storage = nil)
79
81
  case storage
80
82
  when Symbol
81
- if storage_engine = storage_engines[storage]
83
+ if (storage_engine = storage_engines[storage])
82
84
  self._storage = eval storage_engine
83
85
  else
84
86
  raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
@@ -124,7 +126,7 @@ module CarrierWave
124
126
  @#{name} = nil
125
127
 
126
128
  def self.#{name}(value=nil)
127
- @#{name} = value if value
129
+ @#{name} = value unless value.nil?
128
130
  return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
129
131
  name = superclass.#{name}
130
132
  return nil if name.nil? && !instance_variable_defined?(:@#{name})
@@ -180,8 +182,8 @@ module CarrierWave
180
182
  #
181
183
  def reset_config
182
184
  configure do |config|
183
- config.permissions = 0644
184
- config.directory_permissions = 0755
185
+ config.permissions = 0o644
186
+ config.directory_permissions = 0o755
185
187
  config.storage_engines = {
186
188
  :file => "CarrierWave::Storage::File",
187
189
  :fog => "CarrierWave::Storage::Fog"
@@ -201,6 +203,7 @@ module CarrierWave
201
203
  config.move_to_store = false
202
204
  config.remove_previously_stored_files_after_update = true
203
205
  config.downloader = CarrierWave::Downloader::Base
206
+ config.force_extension = false
204
207
  config.ignore_integrity_errors = true
205
208
  config.ignore_processing_errors = true
206
209
  config.ignore_download_errors = true
@@ -212,6 +215,7 @@ module CarrierWave
212
215
  config.enable_processing = true
213
216
  config.ensure_multipart_form = true
214
217
  config.download_retry_count = 0
218
+ config.download_retry_wait_time = 5
215
219
  end
216
220
  end
217
221
  end
@@ -0,0 +1,66 @@
1
+ require 'active_support'
2
+
3
+ module CarrierWave
4
+ module Uploader
5
+ module Dimension
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before :cache, :check_dimensions!
10
+ end
11
+
12
+ ##
13
+ # Override this method in your uploader to provide a Range of width which
14
+ # are allowed to be uploaded.
15
+ # === Returns
16
+ #
17
+ # [NilClass, Range] a width range which are permitted to be uploaded
18
+ #
19
+ # === Examples
20
+ #
21
+ # def width_range
22
+ # 1000..2000
23
+ # end
24
+ #
25
+ def width_range; end
26
+
27
+ ##
28
+ # Override this method in your uploader to provide a Range of height which
29
+ # are allowed to be uploaded.
30
+ # === Returns
31
+ #
32
+ # [NilClass, Range] a height range which are permitted to be uploaded
33
+ #
34
+ # === Examples
35
+ #
36
+ # def height_range
37
+ # 1000..
38
+ # end
39
+ #
40
+ def height_range; end
41
+
42
+ private
43
+
44
+ def check_dimensions!(new_file)
45
+ # NOTE: Skip the check for resized images
46
+ return if version_name.present?
47
+ return unless width_range || height_range
48
+
49
+ unless respond_to?(:width) || respond_to?(:height)
50
+ raise 'You need to include one of CarrierWave::MiniMagick, CarrierWave::RMagick, or CarrierWave::Vips to perform image dimension validation'
51
+ end
52
+
53
+ if width_range&.begin && width < width_range.begin
54
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_width_error", :min_width => ActiveSupport::NumberHelper.number_to_delimited(width_range.begin))
55
+ elsif width_range&.end && width > width_range.end
56
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_width_error", :max_width => ActiveSupport::NumberHelper.number_to_delimited(width_range.end))
57
+ elsif height_range&.begin && height < height_range.begin
58
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_height_error", :min_height => ActiveSupport::NumberHelper.number_to_delimited(height_range.begin))
59
+ elsif height_range&.end && height > height_range.end
60
+ raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_height_error", :max_height => ActiveSupport::NumberHelper.number_to_delimited(height_range.end))
61
+ end
62
+ end
63
+
64
+ end # Dimension
65
+ end # Uploader
66
+ end # CarrierWave
@@ -14,7 +14,7 @@ module CarrierWave
14
14
  # are allowed to be uploaded.
15
15
  # === Returns
16
16
  #
17
- # [NilClass, Range] a size range which are permitted to be uploaded
17
+ # [NilClass, Range] a size range (in bytes) which are permitted to be uploaded
18
18
  #
19
19
  # === Examples
20
20
  #
@@ -24,7 +24,7 @@ module CarrierWave
24
24
  #
25
25
  def size_range; end
26
26
 
27
- private
27
+ private
28
28
 
29
29
  def check_size!(new_file)
30
30
  size = new_file.size
@@ -66,6 +66,11 @@ module CarrierWave
66
66
  condition = new_processors.delete(:if) || new_processors.delete(:unless)
67
67
  new_processors.each do |processor, processor_args|
68
68
  self.processors += [[processor, processor_args, condition, condition_type]]
69
+
70
+ if processor == :convert
71
+ # Treat :convert specially, since it should trigger the file extension change
72
+ force_extension processor_args
73
+ end
69
74
  end
70
75
  end
71
76
  end # ClassMethods
@@ -78,18 +83,18 @@ module CarrierWave
78
83
 
79
84
  with_callbacks(:process, new_file) do
80
85
  self.class.processors.each do |method, args, condition, condition_type|
81
- if(condition && condition_type == :if)
86
+ if condition && condition_type == :if
82
87
  if condition.respond_to?(:call)
83
88
  next unless condition.call(self, :args => args, :method => method, :file => new_file)
84
89
  else
85
90
  next unless self.send(condition, new_file)
86
91
  end
87
- elsif(condition && condition_type == :unless)
88
- if condition.respond_to?(:call)
89
- next if condition.call(self, :args => args, :method => method, :file => new_file)
90
- else
91
- next if self.send(condition, new_file)
92
- end
92
+ elsif condition && condition_type == :unless
93
+ if condition.respond_to?(:call)
94
+ next if condition.call(self, :args => args, :method => method, :file => new_file)
95
+ elsif self.send(condition, new_file)
96
+ next
97
+ end
93
98
  end
94
99
 
95
100
  if args.is_a? Array
@@ -106,6 +111,15 @@ module CarrierWave
106
111
  end
107
112
  end
108
113
 
114
+ private
115
+
116
+ def forcing_extension(filename)
117
+ if force_extension && filename
118
+ Pathname.new(filename).sub_ext(".#{force_extension.to_s.delete_prefix('.')}").to_s
119
+ else
120
+ filename
121
+ end
122
+ end
109
123
  end # Processing
110
124
  end # Uploader
111
125
  end # CarrierWave
@@ -30,7 +30,20 @@ module CarrierWave
30
30
  # [String] uniquely identifies a file
31
31
  #
32
32
  def identifier
33
- @identifier || storage.try(:identifier)
33
+ @identifier || (file && storage.try(:identifier))
34
+ end
35
+
36
+ ##
37
+ # Returns a String which is to be used as a temporary value which gets assigned to the column.
38
+ # The purpose is to mark the column that it will be updated. Finally before the save it will be
39
+ # overwritten by the #identifier value, which is usually #filename.
40
+ #
41
+ # === Returns
42
+ #
43
+ # [String] a temporary_identifier, by default @original_filename is used
44
+ #
45
+ def temporary_identifier
46
+ @original_filename || @identifier
34
47
  end
35
48
 
36
49
  ##
@@ -40,8 +53,8 @@ module CarrierWave
40
53
  #
41
54
  # [String] contents of the file
42
55
  #
43
- def read
44
- file.try(:read)
56
+ def read(*args)
57
+ file.try(:read, *args)
45
58
  end
46
59
 
47
60
  ##