カスタムバリデータでActive Storageでのファイルアップロードを検証

①appディレクトリ配下にvalidatorsディレクトリを作成。

②validatorsディレクトリ配下にバリデータファイルを作成。

$ touch app/validators/attachment_validator.rb


③バリデータファイルに検証内容を記載。

カスタムバリデータの規則
  1. クラス名は<検証名>Validatorの形式で命名
  2. ActiveModel::EachValidatorクラスを継承。
  3. validate_eachメソッドを実装。
# モデルで呼び出す際はattachmentで呼び出す。
class AttachmentValidator < ActiveModel::EachValidator
  include ActiveSupport::NumberHelper

  # recordにはモデルのインスタンス、attributeには属性名、valueには属性値が入る。
  def validate_each(record, attribute, value)
    return if value.blank? || !value.attached?

    has_error = false

    # オプションにmaximumがあればvalidate_maximumを実行。
    # validate_maximumがfalseならhas_errorにtrueを代入。
    if options[:maximum]
      has_error = true unless 
                  validate_maximum(record, attribute, value)
    end

    # オプションにcontent_typeがあればvalidate_content_typeを実行。
   # validate_content_typeがfalseならhas_errorにtrueを代入。
    if options[:content_type]
      has_error = true unless 
                  validate_content_type(record, attribute, value)
    end

    # オプションのpurgeがtrueかつhas_errorがtrueなら属性値を削除。
    record.send(attribute).purge if options[:purge] && has_error
  end

  private

  # ファイルサイズがmaximumで指定しているより大きければエラーを表示。
  # そしてfalseを返す。
  def validate_maximum(record, attribute, value)
    if value.byte_size > options[:maximum]
      record.errors[attribute] << (options[:message] || 
     "#{number_to_human_size(options[:maximum])}以下にしてください")
      false
    else
      true
    end
  end

  # ファイルタイプがcontent_typeで指定しているものでなければエラーを表示。
  # そしてfalseを返す。
  def validate_content_type(record, attribute, value)
    if value.content_type.match?(options[:content_type])
      true
    else
      record.errors[attribute] << (options[:message] || 'は対応できないファイル形式です')
      false
    end
  end
end


④モデルで呼び出す。

validates :og_image, attachment: { purge: true, 
                            content_type: %r{\Aimage/(png|jpeg)\Z}, 
                                 maximum: 524_288_000 }
validates :favicon, attachment: { purge: true, 
                           content_type: %r{\Aimage/png\Z}, 
                                maximum: 524_288_000 }



参考記事:
Rails カスタムバリデーション(validator, EachValidator) - Qiita
Rails tips: カスタムバリデータクラスを作る(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社