Let's say I've got 15 user ids in an array called user_ids.

If I want to, say, change all of their names to "Bob" I could do:

users = User.find(user_ids)
users.update_all( :name => 'Bob' )

This doesn't trigger callbacks, though. If I need to trigger callbacks on these records saving, to my knowledge the only way is to use:

users = User.find(user_ids)
users.each do |u|
  u.name = 'Bob'
  u.save
end

This potentially means a very long running task in a controller action, however.

So, my question is, is there any other better / higher performance / railsier way to trigger a batch update to a set of records that does trigger the callbacks on the records?


Instead of using each/find_each, try using update method instead:

models.update(column: value)

Which is just a wrapper for the following:

models.each{|x| x.update(column: value)}

No, to run callbacks you have to instantiate an object which is expensive operation. I think the only way to solve your problem is to refactor actions that you're doing in callback into separate method that could use data retrieved by select_all method without object instantiation.


Here's another way of triggering callbacks. Instead of using

models.update_all(params)

you can use

models.find_each { |m| m.update_attributes(params) }

I wouldn't recommend this approach if you're dealing with very large amounts of data, though.
Hope it helps!