30
Update Multiple Records at Once in Rails
Rails provides a built-in create method for adding multiple records in single line of code or in more technical term "batch create". For update, if we want to update attributes with same value for all available records then we can do so with the method update_all
. But what if we want to update multiple attributes at once and for multiple records? How do we "batch update" in Rails?
We will be looking at the answer to that question today in this blog.
For updating multiple records at once, there may be two cases; when we want to update
- Same attribute/s in all rows
- Different attributes in each row
To update same attributes with same values in all rows of the table, we can use the Rails method update_all
For e.g. If we want to update all users with first_name
"John" to "Jessica", we can do so with following code:
User.where(first_name: 'John').update_all(first_name: 'Jessica')
Let's suppose we have a model User and we want to update existing records inside with different name.
For e.g. we want to update records with the following JSON:
formatted_users = [
{
id: 1,
name: 'John Doe'
},
{
id: 2,
name: 'Jessica Jones'
},
{
id: 3,
name: 'Robert Junior'
}
]
Did you notice? Each user has different name that needs to be updated.
Let's see how we can update multiple records like these at once in Rails.
-
Index records by their id
First of all, we should index all records by their id, index_by will return records grouped by the id and all records will be inside the hash.
grouped_users = formatted_users.index_by( {|user| user[:id]}) # index_by will return the following hash # => {1=>{:id=>1, :name=>"John Doe"}, 2=>{:id=>2, :name=>"Jessica Jones"}, 3=>{:id=>3, :name=>"Robert Junior"}}
-
Update grouped records
After grouping all records by their id, we will pass all ids as a first argument and their attributes as the second attribute to the method update. This way all our records will be updated at once without us having to loop through each record and calling
update
each time.
User.update(grouped_users.keys, grouped_users.values)
This way we can update multiple records with different attributes from a hash or JSON.
One thing to note is, this solution is not optimized or efficient for large set of records because for each record, we will be hitting database with the update query. That can take significant memory and also more time to execute large set of records.
Do you have more optimized solutions? Let us know in the comment.
Thank you for reading. Happy Coding!
- Cover Image by salvatore ventura on Unsplash