Tintin81
Tintin81

Reputation: 10207

How to change CarrierWave's min_size & max_size error messages?

I am using the following method to validate the file size of my images:

class ImageUploader < CarrierWave::Uploader::Base

  def size_range
    0..200.kilobytes
  end

Unfortunately, the error message that my users are getting is a bit cryptic:

Image size should be less than 204800

Is there a way to change that to something more meaningful such as:

Image size should be less than 2 MB

I've tried various approaches but to no avail.

These are my localization files by the way:

errors:
  messages:
    min_size_error: size should be greater than %{min_size}
    max_size_error: size should be less than %{max_size}

Thanks for any help.

Upvotes: 1

Views: 1749

Answers (3)

Rajarshi Das
Rajarshi Das

Reputation: 12320

You can change the validation message by custom validator

like below

class Product < ActiveRecord::Base 
  mount_uploader :file,  ImageUploader
  validate :up_file_size
  validate :down_file_size

  def up_file_size
    if file.file.size.to_f/(1000*1000) > 200.kilobytes
      errors.add(:file, "size should be less than #{max_upload_limit.to_f}MB")
    end
  end

 def down_file_size
    if file.file.size.to_f/(1000*1000) < 0
      errors.add(:file, "size should be greater than #{min_upload_limit.to_f}MB")
    end
  end
 end

Upvotes: 1

Alex Kojin
Alex Kojin

Reputation: 5204

To make an error message more friendly override carrierwave's check_size! method in your FileUploader with below code:

class ImageUploader < CarrierWave::Uploader::Base

  def size_range
    0..200.kilobytes
  end

  private

  def check_size!(new_file)
    size = new_file.size
    expected_size_range = size_range
    if expected_size_range.is_a?(::Range)
      if size < expected_size_range.min
        raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_size_error", :min_size => ApplicationController.helpers.number_to_human_size(expected_size_range.min))
      elsif size > expected_size_range.max
        raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_size_error", :max_size => ApplicationController.helpers.number_to_human_size(expected_size_range.max))
      end
    end
  end
end

Upvotes: 4

Tom Lord
Tom Lord

Reputation: 28305

By using the built-in file size validator, you are unfortunately tied down to its implementation:

def check_size!(new_file)
  size = new_file.size
  expected_size_range = size_range
  if expected_size_range.is_a?(::Range)
    if size < expected_size_range.min
      raise CarrierWave::IntegrityError,
        I18n.translate(
          :"errors.messages.min_size_error",
          :min_size => expected_size_range.min
        )
    elsif size > expected_size_range.max
      raise CarrierWave::IntegrityError,
        I18n.translate(
          :"errors.messages.max_size_error",
          :max_size => expected_size_range.max
        )
    end
  end
end

You could simply override that method to provide some other value for min_size and max_size (e.g. the number of Megabytes rather than Bytes).

Or alternatively, as explained the CarrierWave wiki, you could use a gem like file_validators, or copy this gist, or even quite easily write your own file validator rather than relying on the built-in CarrierWave version.

The simplest custom validator example given on that page (which I'm only copy+pasting here in case the link dies in the future) is:

# app/models/user.rb 
class User< ActiveRecord::Base 
  attr_accessible :product_upload_limit
  has_many :products
end

# app/models/brand.rb 
class Product < ActiveRecord::Base 
  mount_uploader :file, FileUploader
  belongs_to :user
  validate :file_size

  def file_size
    if file.file.size.to_f/(1000*1000) > user.product_upload_limit.to_f
      errors.add(:file, "You cannot upload a file greater than #{upload_limit.to_f}MB")
    end
  end
end

Upvotes: 1

Related Questions