はじめに
複数のモデルを一括でupdate、かつ、コールバックを呼ぶ方法がないのかなと思い、いろいろ探してみました。
で、結論から言うと、コールバックを走らせずに一括updateするのは無理っぽいです><
クラスメソッドとして使えるのは以下の二つですが、まず前提としてどれもコールバックが走りませんでした。
・update_all
・update_columns
参考:
https://qiita.com/tyamagu2/items/8abd93bb7ab0424cf084
updateを使えばできる?
update
を使えばいけるっぽいという情報を聞いたので実践してみました。
今回はidが1と2のユーザーのage
を20に一括updateするのが目的。
これをupdate_all
と同じ要領でできるかと思ったら?
@users.updaete([1,2], age: 20)
ArgumentError: When assigning attributes, you must pass a hash as an argument
え。。
どうやらもしidと属性の数が合わなかったらrollbackされるようです。
正しくはこうです
@users.update([1,2], [{ age: 20 }, { age: 20 }])
これは非常に面倒臭い。。
しかもidの数だけ属性を書かないといけません。
なぜこのような仕様にしたのでしょうか。。
参考: http://o.inchiki.jp/obbr/198
ならばバルクアップデートはどうだろう
と思い、こんな感じに早速やってみた。
users = []
@users.each do |user|
user.age = 20
users << user
end
User.import users, on_duplicate_key_update: [:age]
が、updateはされてもコールバックは呼ばれず。。
結論
一個づつupdateしよう;;
@users.each { |user| user.update(age: 20) }
はい、結局これに落ち着きました。。
もし他にやり方があるよ!っていう神様がいましたら教えていただけると飛んで喜びます(m_ _m)