セキュリティ系の勉強、その他開発メモとか雑談. GithubはUnity触っていた頃ものがメイン 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))

とかどうでしょう?

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