ActiveModel::EachValidator
ActiveModel::EachValidatorを継承したクラスでは、validate_eachというインスタンスメソッドにバリデーションルールを実装します。record、attribute、valueという引数については、後ほど解説いたします。
実装
class AttachmentValidator < ActiveModel::EachValidator include ActiveSupport::NumberHelper def validate_each(record, attribute, value) return if value.blank? || !value.attached? has_error = false if options[:maximum] has_error = true unless validate_maximum(record, attribute, value) end if options[:content_type] has_error = true unless validate_content_type(record, attribute, value) end record.send(attribute).purge if options[:purge] && has_error end private 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 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
record、attribute、valueについて
record:バリデーション対象のオブジェクト
[1] pry(#<AttachmentValidator>)> record => #<Site:0x00007fd0418d2160 id: 1, name: "Blog", subtitle: "Very awesome!", description: "", created_at: Sun, 27 Jun 2021 17:42:08 JST +09:00, updated_at: Tue, 29 Jun 2021 22:51:10 JST +09:00>
attribute: バリデーション対象の属性名
[2] pry(#<AttachmentValidator>)> attribute => :og_image
value:属性名の値
[3] pry(#<AttachmentValidator>)> value => #<ActiveStorage::Attached::One:0x00007fd04b6bd6e0 @dependent=:purge_later, @name="og_image", @record= #<Site:0x00007fd0418d2160 id: 1, name: "Blog", subtitle: "Very awesome!", description: "", created_at: Sun, 27 Jun 2021 17:42:08 JST +09:00, updated_at: Tue, 29 Jun 2021 22:51:10 JST +09:00>>
定義したバリデーション ルールの呼び出し
定義したバリデーションルールは、validatesメソッドの呼び出し時にオプションとして指定できるようになります。
class Site < ApplicationRecord has_one_attached :og_image has_one_attached :favicon has_many_attached :main_images validates :name, presence: true, length: { maximum: 100 } validates :subtitle, length: { maximum: 100 } validates :description, length: { maximum: 400 } 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 } end