-
-
Save denyago/1298417 to your computer and use it in GitHub Desktop.
| en: | |
| errors: | |
| messages: | |
| wrong_content_type: "is the wrong content type" |
| # Based on: https://gist.github.com/1009861 | |
| class FileMimeTypeValidator < ActiveModel::EachValidator | |
| MESSAGES = { :content_type => :wrong_content_type }.freeze | |
| CHECKS = [ :content_type ].freeze | |
| DEFAULT_TOKENIZER = lambda { |value| value.split(//) } | |
| RESERVED_OPTIONS = [:content_type, :tokenizer] | |
| def initialize(options) | |
| super | |
| end | |
| def check_validity! | |
| keys = CHECKS & options.keys | |
| if keys.empty? | |
| raise ArgumentError, 'Patterns unspecified. Specify the :content_type option.' | |
| end | |
| keys.each do |key| | |
| value = options[key] | |
| unless valid_content_type_option?(value) | |
| raise ArgumentError, ":#{key} must be a String or a Regexp or an Array" | |
| end | |
| if key.is_a?(Array) && key == :content_type | |
| options[key].each do |val| | |
| raise ArgumentError, "#{val} must be a String or a Regexp" unless val.is_a?(String) || val.is_a?(Regexp) | |
| end | |
| end | |
| end | |
| end | |
| def validate_each(record, attribute, value) | |
| raise(ArgumentError, "A CarrierWave::Uploader::Base object was expected") unless value.kind_of? CarrierWave::Uploader::Base | |
| value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String) | |
| return if value.length == 0 | |
| CHECKS.each do |key| | |
| next unless check_value = options[key] | |
| if key == :content_type | |
| if check_value.is_a?(String) || check_value.is_a?(Regexp) | |
| do_validation(value, check_value, key, record, attribute) | |
| else | |
| check_value.each do |pattern| | |
| do_validation(value, pattern, key, record, attribute) | |
| end | |
| end | |
| end | |
| end | |
| end | |
| def help | |
| Helper.instance | |
| end | |
| class Helper | |
| include Singleton | |
| include ActionView::Helpers::NumberHelper | |
| end | |
| private | |
| def valid_content_type_option?(content_type) | |
| return true if %w{Array String Regexp}.include?(content_type.class.to_s) | |
| false | |
| end | |
| def do_validation(value, pattern, key, record, attribute) | |
| return if value.file.content_type.send((pattern.is_a?(String) ? "==" : "=~" ), pattern) | |
| errors_options = options.except(*RESERVED_OPTIONS) | |
| default_message = options[MESSAGES[key]] | |
| errors_options[:message] ||= default_message if default_message | |
| record.errors.add(attribute, MESSAGES[key], errors_options) | |
| end | |
| end |
| class Post < ActiveRecord::Base | |
| mount_uploader :image, ImagePostUploader | |
| validates :image, | |
| :file_mime_type => { | |
| :content_type => /image/ | |
| } | |
| end |
Thanks for this! It works almost as I hoped. However, whenever I upload an unvalid file it raises ActiveRecord::RecordInvalid exception, instead of the usual flash notice.
Validation failed: Image Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: Command ("identify -ping /var/folders/90/bt4jhsys70d71dfhr06q3crh0000gn/T/mini_magick20130722-17393-19zaaq0.html") failed: {:status_code=>1, :output=>"identify: delegate failed \"html2ps\" -U -o \"%o\" \"%i\"' @ error/delegate.c/InvokeDelegate/1065.\nidentify: unable to open image /var/tmp/magick-17517Qh--EFN7KBBh': No such file or directory @ error/blob.c/OpenBlob/2638.\nidentify: unable to open file /var/tmp/magick-17517Qh--EFN7KBBh': No such file or directory @ error/constitute.c/ReadImage/589.\n"}, Image is the wrong content type
Is it possible to correct this behavior? (I'm a rails newbie and need some points on how to do it myself)
Hi Denis, cool validator thanks for that.
But I use it like this:
validates :icon,
:file_mime_type => {
:content_type => ['image/jpeg', 'image/png', 'image/gif'],
:if => :has_icon?
}and in this case I've got 2 errors for each of invalid content_type.
that is why I've got update for you:
- def validate_each(record, attribute, value) looks like this for me:
def validate_each(record, attribute, value)
raise(ArgumentError, "A CarrierWave::Uploader::Base object was expected") unless value.kind_of? CarrierWave::Uploader::Base
value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String)
return if value.length == 0
CHECKS.each do |key|
next unless check_value = options[key]
do_validation(value, check_value, key, record, attribute) if key == :content_type
end
end- and def do_validation(value, pattern, key, record, attribute)
def do_validation(value, pattern, key, record, attribute)
if pattern.is_a?(String) || pattern.is_a?(Regexp)
return if value.file.content_type.send((pattern.is_a?(String) ? "==" : "=~" ), pattern)
else
valid_list = pattern.map do |p|
value.file.content_type.send((p.is_a?(String) ? "==" : "=~" ), p)
end
return if valid_list.include?(true)
end
errors_options = options.except(*RESERVED_OPTIONS)
default_message = options[MESSAGES[key]]
errors_options[:message] ||= default_message if default_message
record.errors.add(attribute, MESSAGES[key], errors_options)
end
Validation logic working fine with me, but the problem is that; active record every time run this validator even when no file is uploaded. So this obviously fails. Is there any way to tackle this situation?