[Rails]carrierwaveのcallbackをskip


Railsで画像アップロード機能を作る際に欠かせないgemと言えば carrierwave ですが、save時にcarrierwaveのcallbackをskipしたい場合の対応方法をメモしておきます。

基本的には昨日の Railsで一時的にbefore_saveをskip で書いたskip_callbackとset_callbackを使えばできます。

carrierwaveのドキュメントに「Skipping ActiveRecord callbacks」という項目があり、そこ見ると以下のcallbackがあると分かります。

# avatarのアップロード機能を持つUserモデル
class User
  mount_uploader :avatar, AvatarUploader
end

# アップローダーに追加されるcallback
after_save :store_avatar!
before_save :write_avatar_identifier
after_commit :remove_avatar! :on => :destroy
before_update :store_previous_model_for_avatar
after_save :remove_previously_stored_avatar

上記のUserモデルを例にcarrierwaveのcallbackをskipしたい場合、以下のようにします。

アバターのダミー画像には、Placehold.jpさんを画像を使用させていただきました。

# carrierwaveのcallbackをskip
User.skip_callback(:save, :after, :store_avatar!)
User.skip_callback(:save, :before, :write_avatar_identifier)
User.skip_callback(:commit, :after, :remove_avatar!)
User.skip_callback(:update, :before, :store_previous_model_for_avatar)
User.skip_callback(:save, :after, :remove_previously_stored_avatar)

# 何かしたい処理を記述
user = User.find(1)
user.remote_avatar_url = 'http://placehold.jp/150x150.png' # avatar画像URL
user.save  # avatarは更新されない

# carrierwaveのcallbackを有効化
User.set_callback(:save, :after, :store_avatar!)
User.set_callback(:save, :before, :write_avatar_identifier)
User.set_callback(:commit, :after, :remove_avatar!)
User.set_callback(:update, :before, :store_previous_model_for_avatar)
User.set_callback(:save, :after, :remove_previously_stored_avatar)

これでcarrierwaveのcallbackを一時的にskipすることができます。

ここ数日、一時的にskipする方法に関する記事ばかりですが、どういうときにこれらを使ったかというのを次の記事でご紹介したいと思います。

参考