LoginSignup
2
2

More than 5 years have passed since last update.

Paperclip で保存する画像のアスペクト比のチェックをする

Posted at

はじめに

Paperclip を使い、取り扱う全ての画像を一括で管理する Picture モデル (ポリモーフィック継承) で、
保存される画像についてそれぞれ異なるアスペクト比をチェックする方法を実装した時のメモ。

実装内容

User のプロフィール画像は、正方形 (縦横は 1 対 1 ) を保持できる
※ 200 × 200 等の画像
Item の画像は、長方形 ( 縦横は 5 対 8 ) を保持できる
※ 400 × 640 等の画像

サンプルソース

app/models/user.rb
class User < ActiveRecord::Base
  has_one :profile_image, class_name: Picture, as: :holder, dependent: :destroy
  accepts_nested_attributes_for :profile_image, allow_destroy: true
end
app/models/item.rb
class Item < ActiveRecord::Base
  has_many :pictures, as: :holder, dependent: :destroy
  accepts_nested_attributes_for :pictures, allow_destroy: true
end
app/models/picture.rb
class Picture < ActiveRecord::Base

  WIDTHS = %i{640 200 142 80}
  STYLES = WIDTHS.map {|width| [:"w#{width}", "#{width}x>"]}.to_h
  PICTURE_TYPES = { user: 1, item: 0.625 } # height / width
  CONTENT_TYPE = %w{image/jpeg image/jpg image/png image/gif}

  belongs_to :holder, polymorphic: true

  has_attached_file :image, { styles: STYLES }
  validates_attachment_size :image, less_than: 1.5.megabytes
  validates_attachment_content_type :image, content_type: CONTENT_TYPE
  validate :validate_image_aspect_ratio, if: -> { image.present? && CONTENT_TYPE.include?(image_content_type) & holder.present? }

  private
  def validate_image_aspect_ratio
    key = holder_type.underscore.to_sym
    if PICTURE_TYPES.keys.include?(key)
      geometry = Paperclip::Geometry.from_file(image.queued_for_write[:original])
      errors.add(:image, :invalid_aspect_ratio) unless PICTURE_TYPES[key] == (geometry.height / geometry.width)
    end
  end
end

サンプルの説明

PICTURE_TYPESholder に当たる useritem のアスペクト比 ( 縦横比 ) を記載し、
validate_image_aspect_ratio でそれらをチェックしています。

image.queued_for_write[:original] でオリジナルのファイルから Paperclip::Geometry オブジェクトを
生成し、縦横のサイズをを取得し、チェックしています。

今後、holder に入るモデルが増える場合は、PICTURE_TYPES にそれぞれ追加することで対応できます。

ただし、1つのモデルが、複数のアスペクト比の画像ファイルを保存できるようになっていないので、
その場合は、下記のよう感じに修正すれば出来るはず。。。チェックしてませんが。

PICTURE_TYPES = { user: [1, 1.6], item: [0.625] } # user に正方形の他の 640 × 400 も追加
errors.add(:image, :invalid_aspect_ratio) unless PICTURE_TYPES[key].include?(geometry.height / geometry.width)
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2