This blog is part of our Rails 5 series.
The update_all method when called on an ActiveRecord::Relation object updates all the records without invoking any callbacks and validations on the records being updated.
Rails 5 supports update method on an ActiveRecord::Relation object that runs callbacks and validations on all the records in the relation.
1 2people = Person.where(country: 'US') 3people.update(language: 'English', currency: 'USD') 4
Internally, the above code runs update method on each Person record whose country is 'US'.
Let's see what happens when update is called on a relation in which validations fail on few records.
We have a Note model. For simplicity let's add a validation that note_text field cannot be blank for first three records.
1class Note < ApplicationRecord 2 validate :valid_note 3 4 def valid_note 5 errors.add(:note_text, "note_text is blank") if id <= 3 && note_text.blank? 6 end 7end
Now let's try and update all the records with blank note_text.
1 2 > Note.all.update(note_text: '') 3 Note Load (0.3ms) SELECT `notes`.* FROM `notes` 4 (0.1ms) BEGIN 5 (0.1ms) ROLLBACK 6 (0.1ms) BEGIN 7 (0.1ms) ROLLBACK 8 (0.1ms) BEGIN 9 (0.1ms) ROLLBACK 10 (0.1ms) BEGIN 11 SQL (2.9ms) UPDATE `notes` SET `note_text` = '', `updated_at` = '2016-06-16 19:42:21' WHERE `notes`.`id` = 3 12 (0.7ms) COMMIT 13 (0.1ms) BEGIN 14 SQL (0.3ms) UPDATE `notes` SET `note_text` = '', `updated_at` = '2016-06-16 19:42:21' WHERE `notes`.`id` = 4 15 (1.2ms) COMMIT 16 (0.1ms) BEGIN 17 SQL (0.3ms) UPDATE `notes` SET `note_text` = '', `updated_at` = '2016-06-16 19:42:21' WHERE `notes`.`id` = 5 18 (0.3ms) COMMIT 19 (0.1ms) BEGIN 20 SQL (3.4ms) UPDATE `notes` SET `note_text` = '', `updated_at` = '2016-06-16 19:42:21' WHERE `notes`.`id` = 6 21 (0.2ms) COMMIT 22 23 => [#<Note id: 1, user_id: 1, note_text: "", created_at: "2016-06-03 10:02:54", updated_at: "2016-06-16 19:42:21">, 24 #<Note id: 2, user_id: 1, note_text: "", created_at: "2016-06-03 10:03:54", updated_at: "2016-06-16 19:42:21">, 25 #<Note id: 3, user_id: 1, note_text: "", created_at: "2016-06-03 12:35:20", updated_at: "2016-06-03 12:35:20">, 26 #<Note id: 4, user_id: 1, note_text: "", created_at: "2016-06-03 14:15:15", updated_at: "2016-06-16 19:14:20">, 27 #<Note id: 5, user_id: 1, note_text: "", created_at: "2016-06-03 14:15:41", updated_at: "2016-06-16 19:42:21">, 28 #<Note id: 6, user_id: 1, note_text: "", created_at: "2016-06-03 14:16:20", updated_at: "2016-06-16 19:42:21">] 29
We can see that failure of validations on records in the relation does not stop us from updating the valid records.
Also the return value of update on AR Relation is an array of records in the relation. We can see that the attributes in these records hold the values that we wanted to have after the update.
For example in the above mentioned case, we can see that in the returned array, the records with ids 1, 2 and 3 have blank note_text values even though those records weren't updated.
Hence we may not be able to rely on the return value to know if the update is successful on any particular record.
For scenarios where running validations and callbacks is not important and/or where performance is a concern it is advisable to use update_all method instead of update method.