Rails 4 批量更新模型数组

Rails 4 bulk updating array of models

我有一组 ActiveRecord 模型,我想重新编号一列并批量更新它们。 代码如下所示:

rules = subject.email_rules.order(:number)
rules.each_with_index do |rule, index|
  rule.number = index + 1
end

EmailRule.update(rules.map(&:id), rules.map { |r| { number: r.number } })

但这会创建 N SQL 个语句,我想要 1 个,有没有办法做到这一点?

您的一个替代方案是将所有交互放在一个事务中,它至少会在最后进行一次提交,从而使其速度更快。

ActiveRecord::Base.transaction do
  ...
end

假设您使用的是 postgres,您可以使用 row_number 和看起来有些奇怪的 UPDATE/FROM 结构。这是基本版本:

UPDATE email_rules target 
SET number = src.idx
FROM (
  SELECT 
    email_rules.id,
    row_number() OVER () as idx
    FROM email_rules
) src
WHERE src.id = target.id

您可能需要将其限定在 subject 上,当然还包括按数字排序,如下所示:

UPDATE email_rules target 
SET number = src.idx
FROM (
  SELECT 
    email_rules.id,
    row_number() OVER (partition by subject_id) as idx
    FROM email_rules
    ORDER BY number ASC
) src
WHERE src.id = target.id

(假设subject_id是关联subjects/email_rules的外键)