2013-09-23 73 views
6

如何在Rails中使用事務塊在一次性更新/保存模型的多個實例?在Rails中的一個ActiveRecord事務中更新多條記錄

我想更新數百條記錄的值;每個記錄的值不同。這是而不是一個屬性的大規模更新情況。 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似乎發出它自己的事務,而不是分批更新到周圍的事務。我希望所有的更新都能在一個大交易中進行。

我該如何做到這一點?

+1

可以是ActiveRecord的導入[寶石](https://github.com/zdennis/activerecord-import/wiki)將爲你工作.. – tihom

回答

0

我不知道,但可能你混淆了多次交易多個查詢

您發佈的代碼將創建單個事務(例如,如果發生異常,則會回滾所有更新),但每個save都會導致單獨的更新查詢。

如果可以使用SQL而不是Ruby代碼執行更新,那麼這可能是最好的方法。

+0

我必須在1000個左右的記錄上同時運行更新,所以我不想運行1000個單獨的更新查詢,因爲它慢得多。你能一次執行它們嗎? – Avishai

+0

如果更新真的是將'score'設置爲2個隨機數的總和(並且您不是僅僅以此爲例來簡化問題),那麼您可以使用'update_all',但使用postgres將該值設置爲'隨機「功能,而不是使用固定值。 – mikej

3

說你知道你想設置與IDS 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

我認爲你只需要改變方法「保存」到「保存!」。 如果有任何更新失敗,該方法保存!生成一個異常。當異常事務塊內發生時,交易反轉整個操作(回滾)

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

這將生成多個SQL請求。 –

相關問題