Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update multiple records in one ActiveRecord transaction in Rails

How can I update/save multiple instances of a model in one shot, using a transaction block in Rails?

I would like to update values for hundreds of records; the values are different for each record. This is not a mass-update situation for one attribute. Model.update_all(attr: value) is not appropriate here.

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

save seems to issue it's own transaction, rather than batching the updates into the surrounding transaction. I want all the updates to go in one big transaction.

How can I accomplish this?

like image 431
Avishai Avatar asked Sep 23 '13 19:09

Avishai


1 Answers

Say you knew that you wanted to set the things with ids 1, 2, and 3 to have scores, 2, 8, and 64 (as opposed to just random numbers), you could:

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;

So with Rails, you'd use ActiveRecord::Base.connection#execute to execute a block similar to the above, but with the correct value string interpolated.

like image 172
dyln Avatar answered Sep 29 '22 18:09

dyln