正確に言うと transaction commit後にした方がいいかも、というお話。
Callback時のCarrierwaveの画像パス
Carrierwaveは保存する時に一旦キャッシュディレクトリに画像をキャッシュする作りになっている。デフォルトだとpublic/uploads/tmp/...
に入る。
ここで気をつけないといけないのが、after_createやafter_updateのcallback内では、@model.hoge_urlは キャッシュディレクトリのパスを返す。
例えば、Callback時に別のサーバなりに画像のファイルパスを送るようなユースケースの場合、誤ってこのキャッシュのURLが送られてしまうことになり、正式なURLを送ることが出来ない。
例
app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
base_path = "images/#{model.class.to_s.pluralize.underscore}/#{model.id}"
end
...
end
config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
region: ENV['AWS_REGION'],
path_style: true
}
config.fog_public = true
config.fog_directory = ENV['FOG_DIRECTORY']
config.asset_host = "https://s3-#{ENV['AWS_REGION']}.amazonaws.com/#{ENV['FOG_DIRECTORY']}"
end
app/models/hoge.rb
class Hoge < ApplicationRecord
mount_uploader :image, ImageUploader
after_create :send_image
private
def send_image
# POST to Another Applications etc...
# self.image_url #=> /public/uploads/tmp/... となってしまう
end
end
どうすれば良いのか
after_commitを使いましょう。
app/models/hoge.rb
class Hoge < ApplicationRecord
mount_uploader :image, ImageUploader
after_commit :send_image, on: :create
private
def send_image
# POST to Another Applications etc...
# self.image_url #=> /public/uploads/tmp/... となってしまう
end
end
Railsで画像を扱うときにはCarrierwaveを使う人が多いと思うが、思わぬところではまったのでメモ。
トランザクション確定してないくせに別サーバにPOSTしに行くなんてなにを考えて