Minstrel

Ruby, JavaScript, Haskell, Math, Music, Design

ActiveRecord#update_allでtimestampが記録されない

社内のマーケターに、「このレコードの更新日おかしくないですか?」と相談され、表題の事件が発覚。

ActiveRecord#update_allでtimestampが記録されない

更新されまくっているレコードなのに、created_atとupdated_atが一致していておかしいと思い、ActiveRecordのソースを見に行った。 以下、わかったこと。

事実①

callbacksが呼ばれないメソッドがある。 これはRailsGuideにものっていたが改めてまとめる。

callback呼ばれないメソッド達

decrement
decrement_counter
delete
delete_all
increment
increment_counter
toggle
touch
update_column
update_columns
update_all
update_counters

callbackをスキップするというのは、モデルの一貫性を一瞬でぶち壊すので これらのメソッドの使用は原則禁止にするのが良さそうです。。

callback呼ばれるメソッド達

create
create!
destroy
destroy!
destroy_all
save
save!
save(validate: false)
toggle!
update_attribute
update
update!
valid?

事実②

timestampsはcallbackによって呼び出される。 ActiveRecordさんのメタプロ力が強すぎて、完璧には理解できなかったがどうやらafter_create, after_update, after_commitあたりで呼ばれていそう。

これによって update_allを使用 -> callbackが呼ばれない -> timestampが記録されない という掲題の事象が起きていた。