According to the Rails docs here and here, using update_all
does not do the following -
updated_at
field:limit
and :order
methodsI'm trying to go through my code base and remove instances of update_all
, particularly because of the first point.
Is there a way to still have the convenience of update_all
and still run validations? I understand that I can loop through each record and save it, but that's not only messier visually but also more more inefficient because it executes N SQL statements instead of 1
# before User.where(status: "active").update_all(status: "inactive") # after User.where(status: "active").each { |u| u.update(status: "inactive") }
Thanks!
Edit: I'm using Rails 4.2
Does Update_all trigger callbacks in rails? permalink #update_all(updates) ⇒ Object It does not instantiate the involved models and it does not trigger Active Record callbacks or validations.
ActiveRecord's update_all() returns the number of records updated.
Rails validation defines valid states for each of your Active Record model classes. They are used to ensure that only valid details are entered into your database. Rails make it easy to add validations to your model classes and allows you to create your own validation methods as well.
Timestamps. Note that ActiveRecord will not update the timestamp fields (updated_at/updated_on) when using update_all().
Unfortunately update_all
is way faster because it doesn't instantiate an active record object for each record and instead deals directly with the database. In your case, since you need validations and callbacks, you'll need to instantiate the objects and so you're best bet is iterating in batches of 1000 and performing the update as originally shown. Such as:
User.where(status: "active").find_each { |u| u.update(status: "inactive") }
The find_each
method only loads 1000 objects at a time thus not overloading the garbage collector. If you have bulk records in the hundreds of thousands of rows I'd consider going back to update_all or moving the updating to a background task since it can easily cause a timeout when deployed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With