Ruby
Rails
carrierwave

Carrierwaveの画像パスをCallbacksで扱う時はafter_commitを使ったほうが良いかも

正確に言うと 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しに行くなんてなにを考えて

参考 -StackOverflow