How to save a model without running callbacks in Rails

南笙酒味 提交于 2019-11-30 06:01:30

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.

rafroehlich2

To disable en-mass callbacks use...

Survey.skip_callback(:save, :before, :calculate_averages)

Then to enable them...

Survey.set_callback(:save, :before, :calculate_average)

This skips/sets for all instances.

Ahmad Hussain

update_column is an ActiveRecord function which does not run any callbacks, and it also does not run validation.

Swaps

If you want to conditionally skip callbacks after checking for each survey you can write your custom method.

For ex.

  • Modified callback-

`

before_save :calculate_averages, if: Proc.new{ |survey| !survey.skip_callback }

`

  • New instance method-

`

def skip_callback(value = false)
  @skip_callback = @skip_callback ? @skip_callback : value
end

`

  • Script to update surveys-

`

Survey.all.each do |survey|
  survey.some_average = (survey.some_value + survey.some_other_value) / 2.to_f
  #and some more averages...
  survey.skip_callback(true)
  survey.save!
end

`

Its kinda hack but hope will work for you.

Doesn't work for Rails 5

Survey.skip_callback(:save, :before, :calculate_average) 

Works for Rails 5

Survey.skip_callback(:save, :before, :calculate_average, raise: false)

https://github.com/thoughtbot/factory_bot/issues/931

Sherwyn Goh

hopefully this is what you're looking for.

https://stackoverflow.com/a/6587546/2238259

For your second issue, I suspect it would be better to inspect when this calculation needs to happen, it would be best if it could be handled in batch at a specified time where network traffic is at its trough.

EDIT: Woops. I actually found 2 links but lost the first one, apparently. Hopefully you have it fixed.

Rafeeq

For Rails 3 ActiveSupport::Callbacks gives you the necessary control. You can reset_callbacks en-masse, or use skip_callback to disable judiciously like this:

Vote.skip_callback(:save, :after, :add_points_to_user)

…after which you can operate on Vote instances with :add_points_to_user inhibited

Rails 5.2.3 requiring an after party script to NOT trigger model events, update_column(column_name, value) did the trick:

task.update_column(task_status, ReferenceDatum::KEY_COMPLETED)

https://apidock.com/rails/ActiveRecord/Persistence/update_column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!