Как обновить все, когда нужны обратные вызовы? - PullRequest
40 голосов
/ 03 августа 2011

Допустим, у меня есть 15 идентификаторов пользователей в массиве с именем user_ids.

Если я хочу, скажем, изменить все их имена на "Боб", я мог бы сделать:

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

Однако это потенциально означает очень долгое выполнение задачи в действии контроллера.

Итак, мой вопрос заключается в том, есть ли другой способ лучше / выше производительность / railsier для запуска пакетного обновления набора записей, которые вызывает обратные вызовы на записи?

Ответы [ 3 ]

30 голосов
/ 12 июля 2017

Вместо использования каждого / find_each, попробуйте вместо этого использовать метод update:

models.update(column: value)
22 голосов
/ 03 августа 2011

Нет, для запуска обратных вызовов вам нужно создать экземпляр объекта, который является дорогостоящей операцией.Я думаю, что единственный способ решить вашу проблему - это преобразовать действия, которые вы выполняете в обратном вызове, в отдельный метод, который может использовать данные, полученные методом select_all, без создания объекта.

18 голосов
/ 13 мая 2014

Вот еще один способ вызвать обратные вызовы.Вместо использования

models.update_all(params)

вы можете использовать

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

Я бы не рекомендовал этот подход, если вы имеете дело с очень большими объемами данных.
Надеюсьпомогает!

...