Help us understand the problem. What is going on with this article?

ActiveRecord のコールバックを特定のコントローラーの処理のときのみ実行する

はじめに

ActiveRecord のコールバックを、特定のモデルの状態というよりは、特定のコントローラーの処理の場合のみ実行したい場合について考えたので、簡単にやり方をまとめます。

tl;dr

方針としては、コントローラーにモデルのインスタンス変数でフラグを付けてあげて、そのフラグが立っている場合のみ実行するという形にしました。

今回は Post モデルの statuscreate 時にのみ 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: のようなコンテキストが使えなかったのでどうしようか悩んでいたのですが、一旦この形でできました。

他にいい方法ご存知でしたら教えて下さい!

参考

sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業
http://www.sonicgarden.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away