問題
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