Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

前提

  • 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にも以下のように書いてありました。

https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Use-a-timestamp-in-file-names

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

その他

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away