セキュリティ系の勉強・その他開発メモとか雑談. Twitter, ブログカテゴリ一覧
本ブログはあくまでセキュリティに関する情報共有の一環として作成したものであり,公開されているシステム等に許可なく実行するなど、違法な行為を助長するものではありません.

【RubyOnRails】after_initializeとFactoryBot

//

ActiveRecordのコールバック

まずは下のサイトさんをご覧ください。

qiita.com

# Hoge.create()の実行順

hoge = Hoge.new(name: "hoge")
#initialize
after_initialize #newメソッドで生成したときのみ
hoge.save!
#BEGIN TRANSACTION
before_validation
#validation
after_validation
#ROLLBACK
after_rollback   #validationに失敗した時のみ
before_save
around_save
before_create
around_create
#INSERT INTO "hoges"
after_create
after_save
# COMMIT
after_commit
# 引用元:https://qiita.com/rtoya/items/29cef3e328299781a328

(引用元ではafter_initializenewの時のみとありますが、インスタンスが生成されるたびに呼ばれるので、Hoge.createHoge.first等を使用した場合も呼ばれるはずです。)

で今回after_initializeで呼ばれるメソッドをテストしたかったというお話です。

そもそも

上に書いたように、newで呼ぶ以外にもafter_initializeを走らせる方法はたくさんあるので、基本的にモデルのコールバックテストをするのには困らないはずです。

ですが、私はFactoryBot.new(:hoge)を呼ぶと同時にafter_initializeを見ようとしたためハマりました。

FactoryBot.create(:hoge)と、Hoge.create()

てっきり同じように呼ばれるのかと思いきや、若干違うようです。
createの引数に初期値を渡してインスタンスを生成する場合、FactoryBotの方はafter_initialize時に初期値がまだ反映されません。

つまり..

本家のHoge.create(name: "hoge")

#initialize
after_initialize # すでにself.name に"hoge"が入っている
hoge.save!
#BEGIN TRANSACTION
before_validation
#validation
after_validation


FactoryBot.create(:hoge,name:"hoge")

#initialize
after_initialize # まだselfは全てnil
hoge.save!
#BEGIN TRANSACTION
before_validation # self.nameに"hoge"が入っている。
#validation
after_validation

という感じになります。

余談

factorybotの値を使うのであれば、

Hoge.create(FactoryBot.attributes_for(:hoge))

とかどうでしょう?

よく理解できていないので、何かあれば教えてください。