Carrierwave + S3でのS3 object keyの決まり方
store
storeメソッドででFog gem経由でクラウドストレージに置きに行く
code:for.rb
##
# Write file to service
#
# === Returns
#
# Boolean true on success or raises error def store(new_file)
if new_file.is_a?(self.class)
new_file.copy_to(path)
else
fog_file = new_file.to_file
@content_type ||= new_file.content_type
@file = directory.files.create({
:body => fog_file ? fog_file : new_file.read,
:content_type => @content_type,
:key => path,
:public => @uploader.fog_public
}.merge(@uploader.fog_attributes))
fog_file.close if fog_file && !fog_file.closed?
end
true
end
pathというのがs3 objectのkeyになる
path
code:sanitized_file.rb
##
# Returns the full path to the file. If the file has no path, it will return nil.
#
# === Returns
#
#
def path
return if @file.blank?
if is_path?
File.expand_path(@file)
elsif @file.respond_to?(:path) && !@file.path.blank?
File.expand_path(@file.path)
end
end
FileはSanitizedFileのインスタンス
code:file.rb
def retrieve!(identifier)
path = ::File.expand_path(uploader.store_path(identifier), uploader.root)
CarrierWave::SanitizedFile.new(path)
end
つまりpath == s3 object key == ::File.expand_path(uploader.store_path(identifier), uploader.root) できまる
uploader.store_pathのロジックはこう
code:store.rb
##
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
# used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
#
# === Parameters
#
#
# === Returns
#
#
def store_path(for_file=filename)
end
store_dir + full_filename(これはほぼ \#filename が使われる) になる
code:sanitized_file.rb
def filename
sanitize(original_filename) if original_filename
end
filenameとしては基本アップロードしたファイル名が使われる
ということで基本 store_dir + アップロードしたファイル名 がs3 object keyになる。
model上で mount_uploader して使うとき、Uploader classの実装はだいたいtemplateからこうなる
code:uploader.rb.erb
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
store_dirを上書きして、model名や idを含めている。
なので、 /uploads/User/uploader/2/file.jpg みたいなs3 object keyになる。
---
雑感
S3に上げるだけだと store_dir いらねえよなぁと思う
def store_dir = Rails.env.local? ? "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" : '/'
def filename = SecureRandom.uuid とかでいけないかな...
試してない いけなそう...
dbに永続化した上でファイル保存することになり(つまりs3 object keyをレコード永続化前に得ることができない)場合によっては不便
carrirewaveはContent-TYpeを保存してくれたりする機能がデフォで存在しないなども使い勝手がよくない