2012年9月16日日曜日

ActiveRecord の changed? のバグ


ActiveRecord にはちょっとひどいバグ?がある。

ActiveRecord は save するときに実際に変更のあったカラムのみ
sql の update 文に書き出すようになっている。blob を持つようなモデルやカラム数がやたらと多いモデルの場合には sql が短くて済むので効果がある。

例えば

 u = User.find(1)
 u.name = "山田"
  u.name_changed? #=> true
 u.save
とすると、高速化のために name というカラムだけを更新するような sql が出力される。


同様に、
 u = User.find(1)
 u.save
としても何もカラムが変更されていないため、この場合そもそも sql が発行されない


これは良い仕組みだが、カラムが変更されたかどうかの判定に問題がある。
具体的には、代入が起き、かつ異なる値がセットされたときに変更があったとみなされるため、
gsub! を使った場合変更されたとみなされない。
 u = User.find(1)
 u.name.gsub!("山", "川")
 u.name_changed? #=> false
 u.save #=> なにもおきない

通常フォームからわたってくるデータを突っ込んで保存、という流れを想定しているので
あまり問題にはならないのだと思うが、バッチなどでこのようなコードを書いてしまう可能性はある。


0 件のコメント:

コメントを投稿