LoginSignup
3
1

More than 5 years have passed since last update.

CarrierWave::Uploaderでversionsの拡張子を変更しているとversionsのファイルが出来ないケースがある

Posted at

現象について

画像アップローダのCarrierWaveを使っていて、アップロードされた画像のjpgのサムネイルを作る時、ファイルの拡張子を変えてファイル名を設定しようと以下の様なコードを用意していた。

app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick
  version :thumb do 
    process :convert => "jpg"     
    def full_filename(for_file)
      return unless for_file.present?
      filename = super(for_file)
      filename.chomp(File.extname(filename)) + '.jpg'
    end 
  end
  (他は略)
end
app/models/user.rb
class User < ApplicationRecord
  mount_uploader :image, ImageUploader
end

このUserのimageに image.pngを登録した後、拡張子以外は同じimage.jpgを登録して更新すると、thumb_image.jpgが消えてしまう現象が起きた。
(※ image.pngを登録している段階では、thumb_image.jpgは存在する)

原因

CarrierWaveでは、ファイルを登録後、versionsを作成して古いversionsを削除しているが、この時、古いversionsとファイル名が一緒なため
ファイルを削除する際、新しく作ったversionの画像も削除してしまっている。
元のファイル名が一致した時は削除しないように回避されているが、別のファイル名だがversionsで一致すると言うケースでは回避策が取られていない。(元のソースコードだと発生しないので当然だけど)

対策1: 以前のバージョンのファイルを削除しないようにする

CarrierWaveで画像更新時に以前のバージョンを削除しないを参考に、以前のバージョンを削除しないようにすれば解決はする。
古いファイルが残ってしまうので、使えないケースもありそう

対策2: 生成タイミングを削除タイミングの後にする

バッドノウハウ感のある対策だけど、以下の様に、mount_uploaderでafter_save に作成と削除のコールバックが登録されているので、作成のコールバックを登録し直すことで、削除後に作成する様になる

app/models/user.rb
class User < ApplicationRecord
  mount_uploader :image, ImageUploader
  skip_callback :save, :after, :store_image!
  save_after :store_image!
end

注意: :store_iamge!の imageの部分はカラム名なので、適宜書き換えてください

取り敢えず

対策2を採用したんだけど、もっと良い方法があれば是非指摘ください

3
1
2

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
3
1