はじめに
ActiveRecord のコールバックを、特定のモデルの状態というよりは、特定のコントローラーの処理の場合のみ実行したい場合について考えたので、簡単にやり方をまとめます。
tl;dr
方針としては、コントローラーにモデルのインスタンス変数でフラグを付けてあげて、そのフラグが立っている場合のみ実行するという形にしました。
例
今回は Post
モデルの status
を create
時にのみ created
とつけることを考えます。
やり方
モデルにattr_accessor と after_save の設定
まず、Post
モデルにステータス更新用の update_status
メソッドを定義します。
また、インスタンス変数のフラグを立てるメソッドcreate_executed!
メソッドとフラグ判定メソッド create_executed?
メソッドも作っておきます。
そして、after_save
コールバックで、create_executed?
が true
のときだけ update_status
メソッドを実行する形にしました。
class Post < ApplicationRecord
after_save :update_status, if: :create_executed?
def create_executed!
@create_executed = true
end
def create_executed?
@create_executed == true
end
def update_status
update_columns(status: 'created')
end
end
コントローラーに設定
コントローラー側では、create
メソッドのときに、フラグを立てるメソッドを実行すればOKです。
これにより、create
メソッドの場合のみ、after_save
のコールバックを呼ぶことができます。
class PostsController < ApplicationController
# 中略
def create
@post = Post.new(post_params)
@post.create_executed!
if @post.save
redirect_to posts_path
else
render :new
end
end
# 中略
end
おわりに
after_save
コールバックには、validates
メソッドのon:
のようなコンテキストが使えなかったのでどうしようか悩んでいたのですが、一旦この形でできました。
他にいい方法ご存知でしたら教えて下さい!