54

と呼ばれる配列に15のユーザーIDがあるとしましょうuser_ids

たとえば、すべての名前を「Bob」に変更したい場合は、次のようにします。

users = User.find(user_ids)
users.update_all( :name => 'Bob' )

ただし、これはコールバックをトリガーしません。これらのレコードの保存でコールバックをトリガーする必要がある場合、私の知る限り、唯一の方法は次を使用することです。

users = User.find(user_ids)
users.each do |u|
  u.name = 'Bob'
  u.save
end

ただし、これは、コントローラーアクションで非常に長時間実行されるタスクを意味する可能性があります。

だから、私の質問は、レコードのコールバックをトリガーするレコードのセットへのバッチ更新をトリガーする他のより良い/より高いパフォーマンス/より簡単な方法はありますか?

4

3 に答える 3

69

each / find_eachを使用する代わりに、update代わりにメソッドを使用してみてください。

models.update(column: value)

これは、次のラッパーにすぎません。

models.each{|x| x.update(column: value)}
于 2017-07-12T11:28:10.093 に答える
22

いいえ、コールバックを実行するには、コストのかかる操作であるオブジェクトをインスタンス化する必要があります。問題を解決する唯一の方法は、コールバックで実行しているアクションを、オブジェクトのインスタンス化なしでselect_allメソッドによって取得されたデータを使用できる別のメソッドにリファクタリングすることだと思います。

于 2011-08-03T19:09:15.893 に答える
22

コールバックをトリガーする別の方法は次のとおりです。使用する代わりに

models.update_all(params)

あなたが使用することができます

models.find_each { |m| m.update_attributes(params) }

ただし、非常に大量のデータを処理する場合は、このアプローチはお勧めしません。
それが役に立てば幸い!

于 2014-05-13T18:44:14.620 に答える