前提
- Ruby on Rails で画像投稿機能を実装
- 画像は AWS s3 に保存
ここまでの流れは以下の記事などを参考にしてください。
Railsでcarrierwaveを使ってAWS S3に画像をアップロードする手順を画像付きで説明する
ただ今回の記事の内容では s3 を使用していることは特に関係ありません。
保存する際のファイル名は以下のように現在時刻のタイムスタンプを使用するように変更しました。
class ImageUploader < CarrierWave::Uploader::Base
# (中略)
def filename
"#{Time.now.to_i}-#{original_filename}" if original_filename
end
end
問題
アップロードした画像が「たまに」表示されない(リンク切れしてる)
原因
データベースに保存されている画像のファイル名
1542353427-sample.png
実際のファイル名
1542353428-sample.png
_人人人人人人人_
> 微妙に違う <
 ̄Y^Y^Y^Y^Y^Y^Y ̄
タイムスタンプの下一桁が異なっているので、おそらくどこかで時間に差が出てしまっている、と考えられますね。
Carrierwave 公式のwikiにも以下のように書いてありました。
you might get different timestamps written to the database and the file store.
データベースとファイルストアで違うタイムスタンプになるかもよ、と見事にはめられてしまったような気分です。
解決策
上記リンクを見た方はもう気づいているかと思いますが、Wikiに書いてあるように一時的にタイムスタンプをインスタンス変数として保存して、それをファイル名に利用すればいいのですね。
def filename
@name ||= "#{timestamp}-#{super}" if original_filename.present? and super.present?
end
def timestamp
var = :"@#{mounted_as}_timestamp"
model.instance_variable_get(var) or model.instance_variable_set(var, Time.now.to_i)
end
(上記コードはWikiからコピペしてきました。)
timestamp
メソッドの中ですが、instance_variable_set
は戻り値としてセットした値を返すので、「ゲットする、またはセットする(セットした値を返す)」という処理でうまくいくようです。
その他
この手の問題、過去にも悩まされた気がする...笑