LoginSignup
18
10

More than 5 years have passed since last update.

ActiveStorageとバリデーションエラーの挙動

Last updated at Posted at 2018-04-19
  • ActiveStorage 5.2

 モデルの定義

こんなモデルがあった時のバリデーションエラーの挙動

class Archive
  has_one_attached :zip

  validates :name, presence: true
  validate :zip_should_be_presence

  # https://github.com/rails/rails/issues/31656
  def zip_should_be_presence
    if zip.attached?
      if !blob_is_zip?
        zip.purge # ActiveStorage::Blob.unattachedでお掃除バッチを作ることを考えるとここでpurgeしなくてもいいかも。
        errors.add(:zip, 'はZIPではありません')
      end
    else
      errors.add(:zip, :presence)
    end
  end

  def blob_is_zip?
    zip.blob.content_type == 'application/zip' && zip.blob.filename.extension_without_delimiter == 'zip'
  end
end

添付ファイルでバリデーションエラー

ファイル名をhoge.jpgにしている。今回のモデルの定義ではpurgeを実行するようにしているので削除される。

irb(main):007:0> Archive.create!(name: 'hoge', zip: {io: File.open('hoge.zip'), filename: 'hoge.jpg'})
  Disk Storage (4.1ms) Uploaded file to key: gvRhRYR6kYopMacbhdbATQQH (checksum: mTlNhQT67kf1chY3Gdtydg==)
   (0.1ms)  begin transaction
  ActiveStorage::Blob Create (1.4ms)  INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "byte_size", "checksum", "created_at") VALUES (?, ?, ?, ?, ?, ?, ?)  [["key", "gvRhRYR6kYopMacbhdbATQQH"], ["filename", "hoge.jpg"], ["content_type", "application/zip"], ["metadata", "{\"identified\":true}"], ["byte_size", 326], ["checksum", "mTlNhQT67kf1chY3Gdtydg=="], ["created_at", "2018-04-19 05:19:41.046491"]]
   (1.6ms)  commit transaction
   (0.0ms)  begin transaction
   (0.1ms)  commit transaction
   (0.0ms)  begin transaction
  Disk Storage (0.2ms) Deleted file from key: gvRhRYR6kYopMacbhdbATQQH
  ActiveStorage::Blob Destroy (0.6ms)  DELETE FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ?  [["id", 48]]
   (0.6ms)  rollback transaction
Traceback (most recent call last):
        1: from (irb):7
ActiveRecord::RecordInvalid (バリデーションに失敗しました。 ZipはZIPではありません)

Archiveモデル側でバリデーションエラー

blobは問題ないので特に削除されない。

irb(main):003:0> Archive.create!(zip: {io: File.open('hoge.zip'), filename: 'hoge.zip')
  Disk Storage (4.5ms) Uploaded file to key: rYvGGj9FDYDvgcrCyqn3oVUs (checksum: mTlNhQT67kf1chY3Gdtydg==)
   (0.1ms)  begin transaction
  ActiveStorage::Blob Create (1.5ms)  INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "byte_size", "checksum", "created_at") VALUES (?, ?, ?, ?, ?, ?, ?)  [["key", "rYvGGj9FDYDvgcr
Cyqn3oVUs"], ["filename", "hoge.zip"], ["content_type", "application/zip"], ["metadata", "{\"identified\":true}"], ["byte_size", 326], ["checksum", "mTlNhQT67kf1chY3Gdtydg=="], ["created_at", "2018-04-19 05:18:43.65
2190"]]
   (1.3ms)  commit transaction
   (0.1ms)  begin transaction
   (0.1ms)  commit transaction
   (0.0ms)  begin transaction
   (0.1ms)  rollback transaction
Traceback (most recent call last):
        1: from (irb):3
ActiveRecord::RecordInvalid (バリデーションに失敗しました。 Nameを入力してください。)

迷子のblob

unattachedというお掃除バッチ用のスコープがある。

# https://github.com/rails/rails/pull/31970
ActiveStorage::Blob.unattached.find_each(&:purge_later)

ダイレクトアップロード(先にActiveStorage::Blobを作っておいて、ActiveStorage::Blob#signed_idを使って紐付けを行う仕組み)などを使うとこういうBlobがたくさん作られるので、お掃除バッチの作成は必須ですね。

参考

18
10
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
18
10