LoginSignup
2
1

More than 5 years have passed since last update.

Carrierwave で filename にタイムスタンプを使用するとたまに画像が表示されない問題

Last updated at Posted at 2018-11-16

前提

  • 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は戻り値としてセットした値を返すので、「ゲットする、またはセットする(セットした値を返す)」という処理でうまくいくようです。

その他

この手の問題、過去にも悩まされた気がする...笑

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