I need to calculate values when saving a model in Rails. So I call calculate_averages
as a callback for a Survey
class:
before_save :calculate_averages
However, occasionally (and initially I have 10k records that need this operation) I need to manually update all the averages for every record. No problem, I have code like the following:
Survey.all.each do |survey| survey.some_average = (survey.some_value + survey.some_other_value) / 2.to_f #and some more averages... survey.save! end
Before even running this code, I'm worried the calculate_averages
is going to get called and duplicate this and probably even cause some problems with the way I'm doing things. Ok, so then I think, well I'll just do nothing and let calculate_averages
get called and do its thing. Problem there is, first, is there a way to force callbacks to get called even if you made no changes to the record?
Secondly, the way averages are calculated it's far more efficient to simply not let the callbacks get called at all and do the averages for everything all at once. Is this possible to not let callbacks get called?
Callbacks are methods that get called at certain moments of an object's life cycle. With callbacks it is possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database.
Update attributes in database without saving Callbacks are skipped.
In Rails, callbacks are hooks provided by Active Record that allow methods to run before or after a create, update, or destroy action occurs to an object. Since it can be hard to remember all of them and what they do, here is a quick reference for all current Rails 5 Active Record callbacks.
I believe what you are asking for can be achieved with ActiveSupport::Callbacks
. Have a look at set_callback
and skip_callback
.
In order to "force callbacks to get called even if you made no changes to the record", you need to register the callback to some event e.g. save, validate etc.
.
set_callback :save, :before, :my_before_save_callback
To skip the before_save
callback, you would do:
Survey.skip_callback(:save, :before, :calculate_average).
Please reference the linked ActiveSupport::Callbacks
on other supported options such as conditions and blocks to set_callback
and skip_callback
.
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