詳細に入る前に、要点を説明します。Carrierwaveに、名前付きのファイルをタイムスタンプまたは各ファイルに固有の任意の文字列として保存させる方法を見つけた人はいますか?
デフォルトでは、Carrierwaveは各ファイルとその代替バージョンを独自のディレクトリ(モデルID番号にちなんで名付けられた)に保存します。私はこれが好きではありません。なぜなら、1,000個のディレクトリの代わりに、大きなラウンド数のファイル(私の場合は写真)を使用するために、それぞれ1つまたは2つのファイルを持つ1,000個のサブディレクトリを持つ1つのディレクトリを取得するからです。うん。
ここで、アップローダーのstore_dir
メソッドをオーバーライドして、次のようにすると、次のようになります。
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}"
end
あなたは私が望む正確な振る舞いになってしまいます。すべてのファイル(写真)は、1つの大きな幸せなフォルダーに入れられます。オブジェクトが削除されたときに固執するサブフォルダーはもうありません。
問題は1つだけです。ファイルの衝突。おいしいケーキの2つの異なる写真であっても、delicious_cake.jpgを2回アップロードすると、2番目の写真が最初の写真を上書きします。これが、メソッドが返す値の最後にstore_dir
余分な要素を追加している理由です。/#{model.id}
じゃあ何をすればいいの?少し読んだ後、生成されたアップローダーファイルにコメントアウトされた明らかな解決策があることを発見しました。
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
少し検索した後、私は次のことをした人を見つけました
def filename
@name ||= "#{secure_token}.#{file.extension}" if original_filename
end
これは私に考えさせました、なぜこれをしないのですか
def filename
@name ||= "#{(Time.now.to_i.to_s + Time.now.usec.to_s).ljust(16, '0')}#{File.extname(original_filename)}"
end
それは物事がひどく壊れたときです。これに伴う問題filename
は、ファイルのバージョンごとに呼び出されるように見えるため、最終的に1312335603175322.jpgやthumb_1312335603195323.jpgのようなファイル名になることです。わずかな違いに気づきましたか?filename
各ファイル名は、その特定のバージョンに対して呼び出された時刻に基づいています。それはまったくしません。
model.created_at
次に、タイムスタンプの基準として使用するのに疲れました。最初のバージョンはまだデータベースに配置されていないため、最初のバージョンではnilが返されるという問題が1つだけあります。
さらに考えた後、写真コントローラーで次のことを試してみることにしました。
def create
if params[:picture] and params[:picture][:image]
params[:picture][:image].original_filename = "#{(Time.now.to_i.to_s + Time.now.usec.to_s).ljust(16, '0')}#{File.extname(params[:picture][:image].original_filename)}"
end
...
これは、Carrierwaveが取得する前にoriginal_filenameプロパティをオーバーライドして、タイムスタンプにします。それはまさに私が望むことをします。ファイルの元のバージョンは1312332906940106.jpgのような名前になり、サムネイルバージョン(または他のバージョン)はthumb_1312332906940106.jpgのような名前になります。
しかし、これはひどいハックのようです。これはモデルの一部である必要がありますが、モデルにマウントされているアップローダーの一部である必要があります。
だから、私の質問は、これを達成するためのより良い方法はありますか?これを簡単にするCarrierwaveの重要な何かを見逃しましたか?これについてはそれほど明白ではありませんが、よりクリーンな方法はありますか?動作するコードは良いですが、悪臭のない動作するコードの方が優れています。