6

如何使用 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似乎发出它自己的事务,而不是将更新批量处理到周围的事务中。我希望所有更新都集中在一笔大交易中。

我怎样才能做到这一点?

4

3 回答 3

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可以执行与上述类似的块,但插入了正确的值字符串。

于 2014-01-08T23:39:13.317 回答
1

我不确定,但您可能将多个事务多个查询混淆了。

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

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

于 2013-09-23T20:59:07.837 回答
-2

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

MyModel.transaction do
    things_to_update.each do |thing|
    thing.score = rand(100) + rand(100)
    thing.save!
end
于 2016-12-01T15:08:11.697 回答