Reputation: 1059
I am using Carrierwave and trying to validate the size of images uploaded as well as only allow these file extensions: jpg jpeg png
This works fine by itself
def extension_white_list
%w(jpg jpeg png)
end
This validation works fine
def validate_image_dimensions
minDim = 320
maxDim = 3840
puts screenshot.path
image = MiniMagick::Image.open(screenshot.path)
largestDim = [image[:width], image[:height]].max
smallestDim = [image[:width], image[:height]].min
unless largestDim <= smallestDim * 2
errors.add :screenshot, "maximum dimension of screenshot cannot be more than twice as long as the minimum dimension"
end
#image must be either 320x480, 480x854, 1280x720, 1280x800
unless (image[:width] == 320 && image[:height] == 480) || (image[:width] == 480 && image[:height] == 800) || (image[:width] == 480 && image[:height] == 854) || (image[:width] == 1280 && image[:height] == 720) || (image[:width] == 1280 && image[:height] == 800)
errors.add :screenshot, "Screenshots must have one of these dimensions: 320x480, 480x854, 1280x720, or 1280x800"
end
unless image[:width] >= minDim && image[:height] >= minDim && image[:width] <= maxDim && image[:height]
errors.add :screenshot, "Minimum screenshot dimension is #{minDim}px and maximum screenshot dimension is #{maxDim}px"
end
end
But when I use them both together and try uploading a file with an extension not in the extension_white_list
, like a .mkv file, I get an error in my validate_image_dimensions
validation. The error is thrown on this line
image = MiniMagick::Image.open(screenshot.path)
because MiniMagick is trying to open an image file, but I am giving it a .mkv file.
Is there a way to have Carrierwave first check that the file has a valid extension, and THEN run my validation? Right now, it seems it is running my validation and then checking if the extension is valid.
One solution would be to just check if the file is an image before I run my validate_image_dimensions
validation, but it seems like Carrierwave should first check that the file is of a valid type before doing anything else.
Upvotes: 0
Views: 148
Reputation: 3842
Unfortunately, there's no way to order validations. Custom validations should be able to handle other attributes being invalid without throwing an error. In your case, it doesn't make sense to check the validity of the image if you don't even have an image at all, so you're correct that you need to check that the file is an image at the beginning of your custom validation. The easiest way to do this is to return
if the extension isn't in the whitelist:
return unless extension.in? extension_white_list
The record will still be invalid due to the extension validation, so it won't save regardless.
ETA I wrote the above under the assumption that extension
or a similar method was defined on your model. If you have no way to access the filename extension, you can always rescue
from the error. You don't specify what error is raised on the MiniMagick::Image.open
line. Let's say for now that its MiniMagick::ImageException
. Then you can:
def validate_image_dimensions
…
image = MiniMagick::Image.open(screenshot.path)
…
rescue MiniMagick::ImageException => e
Rails.logger.info "Rescued from MiniMagick::ImageException in validation: #{e.message}"
errors.add :screenshot, "is not a valid image"
end
Upvotes: 1