使用`update_all`时运行验证

use*_*003 13 validation activerecord ruby-on-rails

根据这里这里的Rails文档,使用update_all不执行以下操作 -

  • 它会跳过验证
  • 它不会更新该updated_at字段
  • 它默默地忽略了这些:limit:order方法

我正在尝试通过我的代码库并删除实例update_all,特别是因为第一点.

有没有办法仍然有方便update_all并仍然运行验证?我知道我可以遍历每条记录并保存它,但这不仅在视觉上更混乱,而且效率更低,因为它执行N个SQL语句而不是1

# before
User.where(status: "active").update_all(status: "inactive")
# after
User.where(status: "active").each { |u| u.update(status: "inactive") }
Run Code Online (Sandbox Code Playgroud)

谢谢!

编辑:我正在使用Rails 4.2

bku*_*i01 17

不幸的update_all是,它更快,因为它没有为每条记录实例化一个活动的记录对象,而是直接处理数据库.在您的情况下,由于您需要验证和回调,您需要实例化对象,因此您最好的选择是批量迭代1000并执行最初显示的更新.如:

User.where(status: "active").find_each { |u| u.update(status: "inactive") }
Run Code Online (Sandbox Code Playgroud)

find_each方法一次只加载1000个对象,因此不会使垃圾收集器过载.如果您有数十万行的批量记录,我会考虑返回update_all或将更新移至后台任务,因为它在部署时很容易导致超时.