Help us understand the problem. What is going on with this article?

【日本初?】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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした