問題
ActiveRecordの before_save
、before_update
コールバックに、クライアントコードが直接操作しない属性を設定する処理を書くような機会が結構あると思います。
そこで、次のようなコードを書くわけですが、このコードは意図したどおりに動作しません。理由がすぐにわかるでしょうか?
class Item < ActiveRecord::Base
before_save :prepare_save # This callback doesn't validate
def prepare_save
if hoge_check_ok?
self.checked = true
else
self.checked = false
end
end
end
解答
-
prepare_save
メソッド内でelse
を通ったとき、self.checked = false
の評価値はfalse
-
prepare_save
メソッドの戻り値がfalse
-
before_save
で指定したコールバックの戻り値がfalse
なのでsave
がキャンセルされて DB に保存されない!
教訓
before_xxx
コールバックの最後では self
か true
を返そう。
def prepare_save
if hoge_check_ok?
self.checked = true
else
self.checked = false
end
self
end