在Rails中的一个ActiveRecord事务中更新多个记录

时间:2013-09-23 19:55:39

标签: ruby-on-rails ruby postgresql activerecord transactions

如何使用Rails中的事务块一次更新/保存模型的多个实例?

我想更新数百条记录的值;每条记录的值都不同。这一个属性的批量更新情况。 Model.update_all(attr:value)在这里不合适。

MyModel.transaction do
    things_to_update.each do |thing|
        thing.score = rand(100) + rand(100)
        thing.save
    end
end

save似乎发布了它自己的事务,而不是将更新批处理到周围的事务中。我希望所有更新都进入一次重大交易。

我该如何做到这一点?

3 个答案:

答案 0 :(得分:4)

假设您知道您想要使用ID 1,2和3设置分数,分别为2分,8分和64分(而不是随机数),您可以:

UPDATE 
  things AS t
SET
  score = c.score
FROM 
  (values
    (1, 2),
    (2, 30),
    (4, 50)
  ) as c(id, score) 
 where c.id = t.id;

所以使用Rails,你可以使用ActiveRecord::Base.connection#execute执行类似于上面的块,但是插入了正确的值字符串。

答案 1 :(得分:1)

我不确定,但您可能会将多个交易多个查询混淆

您发布的代码将创建单个事务(例如,如果发生异常,则所有更新都将被回滚),但每个save将导致单独的更新查询。

如果可以使用SQL而不是Ruby代码执行更新,那么这可能是最好的方法。

答案 2 :(得分:-2)

我认为您只需将“保存”更改为“保存!”即可。 如果任何更新失败,方法保存!生成异常。当事务块中发生异常时,事务会反转整个操作(回滚)

MyModel.transaction do
    things_to_update.each do |thing|
    thing.score = rand(100) + rand(100)
    thing.save!
end