【日本初?】CarrierWaveでアップロードされた画像の横幅などをValidateする方法

More than 5 years have passed since last update.

弊社ブログ記事からの転載です

CarrierWaveでアップロードされた画像の横幅などをValidateする方法 @ heathrow.lab

最近CarriweWaveのことばかり書いてる気もしますが、気にせず今回もCarrierWaveです。

例えば横幅100px未満の画像がアップロードされた場合、エラーにしたいってことありますよね。

CarrierWaveにデフォルトでそういうValidatorが提供されていればいいんですが、そうでもないのが悩ましい。

では、どういった方法でやればいいのか。

日本語情報がなかったようのなので、弊社で行っている方法を共有してみます。

# Rmagick使います


下準備

1.画像の横幅縦幅を取得するためCarrierWave::RMagickを拡張

2.画像の横幅縦幅を検証するValidatorクラスを作成

まず、CarrierWave::RMagicを拡張します。

このset_dimensionという関数で

アップロードされた画像をRmagickで読み込んで、横幅縦幅を@dimension保存させます。


config/initializers/carrierwave.rb

module CarrierWave

module RMagick
attr_reader :dimension

def set_dimension
image = Magick::Image.read(current_path).shift
@dimension = { width: image.columns, height: image.rows }
end
end
end


次に、Validatorの作成です。

先ほどの#set_dimensionで保存した横幅縦幅を検証します。


app/validators/image_size_validator.rb

class ImageSizeValidator < ActiveModel::EachValidator

OPTIONS = {
width: {
field: :width,
function: :'==',
message: 'invalid_image_width'
},
max_width: {
field: :width,
function: :'<=',
message: 'invalid_image_max_width'
},
min_width: {
field: :width,
function: :'>=',
message: 'invalid_image_min_width'
},
height: {
field: :height,
function: :'==',
message: 'invalid_image_height'
},
max_height: {
field: :height,
function: :'<=',
message: 'invalid_image_max_height'
},
min_height: {
field: :height,
function: :'>=',
message: 'invalid_image_min_height'
}
}.freeze

def validate_each(object, attribute, value)
return if value.nil? || value.dimension.nil?

dimension = value.dimension
options.each do |key, val|
next unless OPTIONS.key? key
check = OPTIONS[key]
unless dimension[check[:field]].send check[:function], val
object.errors[attribute] << (options[:message] || I18n.t("activerecord.errors.messages.#{check[:message]%[val]}"))
end
end
end
end



使い方

Uploaderに対して#set_dimensionを登録してやります。


app/uploaders/image_uploader.rb

class ImageUploader < CarrierWave::Uploader::Base

include CarrierWave::RMagick

process :set_dimension
end


Modelでこんな風にかけます


app/models/photo.rb

class Photo < ActiveRecord::Base

mount_uploader :image1, ImageUploader
mount_uploader :image2, ImageUploader

# 横幅640px、縦幅920pxでなければならない
validates :image1, presence: true, image_size: { width: 640, height: 920 }

# 横幅が100px以上でなければならない
validates :image2, presence: true, image_size: { min_width: 100 }
end



弊社ブログ記事からの転載です

CarrierWaveでアップロードされた画像の横幅などをValidateする方法 @ heathrow.lab