Paperclip で保存する画像の寸法チェックをする

  • 1
    Like
  • 0
    Comment
More than 1 year has passed since last update.

概要

Paperclipを利用した画像アップロードの際に画像の寸法(height, width)をチェックし、

「横幅XXXpx、縦幅YYYpx以下の画像は許可しない」

といった寸法制限を実現します。

環境

  • Rails 4.2
  • Gem: Paperclip 4.3.0
  • ImageMagick 6.9.5-2

実装

image_dimensions_validator.rb
class ImageDimensionsValidator < ActiveModel::EachValidator

  CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=,
             equal_to: :==, less_than: :<, less_than_or_equal_to: :<= }.freeze
  SIDES = [:width, :height].freeze

  def validate_each(record, attribute, value)
    dimensions = Paperclip::Geometry.from_file(value.queued_for_write[:original].path)

    SIDES.each do |side|
      next if options[side].blank?
      CHECKS.keys.each do |check|
        next if options[side][check].blank? || dimensions.send(side).send(CHECKS[check], options[side][check])
        record.errors[attribute] << "#{side} (#{dimensions.send(side)}px) must be #{check} #{options[side][check]}px"
      end
    end
  end

  def check_validity!
    SIDES.each do |side|
      next if options[side].blank?
      unless CHECKS.keys.any? { |argument| options[side][argument].present? }
        fail ArgumentError, "You must pass either :#{CHECKS.keys.join(', :')} to the validator"
      end
    end
  end
end

オプション

  • :width
  • :height

にそれぞれ、もしくはどちらかにオプションを指定。

オプション.rb
{less_than: INT} # INTより小さい長さの画像ならOK
{less_than_or_equal_to: INT} # INT以下の長さの画像ならOK
{greater_than: INT} # INTより大きい長さの画像ならOK
{greater_than_or_equal_to: INT} # INT以上の長さの画像ならOK
{equal_to: INT} # INTと同じ長さの画像ならOK

使用例

使用例.rb
class SampleImage < ActiveRecord::Base
  has_attached_file :file, IMAGE_OPTIONS
  # widthが640px以上、かつheightが460px以上の画像ならOK
  validates :file, image_dimensions: {
    width: {greater_than_or_equal_to: 640},
    height: {greater_than_or_equal_to: 460}
  }, if: -> {file.dirty?} # upload時のみ寸法のvalidate
  ....
end

参考

thoughtbot/paperclip
ruby on rails - Paperclip image dimensions custom validator - Stack Overflow:
[ruby] dimensions_validator.rb - CodeGist: