LoginSignup
1
1

More than 5 years have passed since last update.

Carrierwaveでfilenameに日時を使いつつresizeしたらfilenameが一致しなくてハマった

Last updated at Posted at 2015-12-09

やりたかったこと

  • 画像アップロード時に時系列で過去分履歴を残したいのでfilenameに日時をいれたい
  • 特定解像度にresizeしたものも用意したい

サンプルコード

  1. filenameをoverrideしてoriginal_filenameに日時を追加する
  2. インスタンス変数化してstore時とupload時のfilenameを一致させる
  3. smallとlargeというversionでresizeする
 class ImageUploader < CarrierWave::Uploader::Base
   include CarrierWave::MiniMagick

   def filename
     @name ||= "#{Time.zone.now.strftime("%Y-%m-%d-%H-%M-%S")}-#{super}" if super
   end

   version :small do
     process resize_to_fill: [100, 100]
   end

   version :large do
     process resize_to_fill: [800, 600]
   end
 end

発生した問題

  • storeしたfilenameとuploadされたfilenameが1秒ずれる
  • resizeしたfileにおいてだけ稀に発生する

原因

   def filename
     @name ||= "#{Time.zone.now.strftime("%Y-%m-%d-%H-%M-%S")}-#{super}" if super
   end

ここでnameをインスタンス変数化することで、resize時にもfilenameが同一になるだろうと考えていた。
しかし実際resize時の処理はCarrierwave内部でcallbackとして呼びだされ、同クラスの別インスタンスを生成して行われる。
その結果resize時には別インスタンスでこのfilenameが呼ばれるため、nameはnilとなり処理時刻で生成されるためだった。

解決方法

rezise時のfilenameとして、原寸画像Upload時のインスタンスのものを使うように指定した。

コード変更点

   version :small do
     process resize_to_fill: [100, 100]
+
+    def filename
+      model.send(mounted_as).filename
+    end
   end

   version :large do
     process resize_to_fill: [800, 600]
+
+    def filename
+      model.send(mounted_as).filename
+    end
   end

model.send(mounted_as)は、マウントしてるmodelのattributeです。
Versionの処理内でこれを呼び出すことで原寸画像Upload時のインスタンスを取得しています。

これ解決一応したけどversion毎に毎回これ指定するの面倒なので、もっといい解決方法あるんじゃないのか?とも思うので、もっといい方法あったら追記します。

参考

1
1
1

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