如何在不运行Rails中的回调的情况下保存模型

我需要在Rails中保存模型时计算值。 所以我将calculate_averages称为Survey类的回调:

 before_save :calculate_averages 

但是,偶尔(最初我有10k记录需要此操作)我需要手动更新每条记录的所有平均值。 没问题,我有以下代码:

 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 

在运行此代码之前,我担心calculate_averages会被调用并复制它,甚至可能会导致我正在做事的方式出现问题。 好吧,那么我想,好吧,我什么都不做,让calculate_averages被调用并做其事。 问题是,首先,即使您没有对记录进行任何更改,是否有办法强制回调被调用?

其次,计算平均值的方式更有效率,根本不让回调被调用,并一次性完成所有事件的平均值。 这可能不会让回调被调用吗?

我相信你所要求的是使用ActiveSupport::Callbacks可以实现的。 看看set_callbackskip_callback

为了“即使您没有对记录进行任何更改也强制调用回调”,您需要将回调注册到某些事件,例如save, validate etc.

 set_callback :save, :before, :my_before_save_callback 

要跳过before_save回调,您可以:

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

请在其他支持的选项(如条件和块)上引用链接的ActiveSupport::Callbacksset_callbackskip_callback

要禁用en-mass回调,请使用…

 Survey.skip_callback(:calculate_averages) 

然后启用它们……

 Survey.set_callback(:calculate_average) 

这会跳过/设置所有实例。

update_column是一个ActiveRecord函数,它不运行任何回调,也不运行validation。

如果您想在检查每个调查后有条件地跳过回调,则可以编写自定义方法。

对于前者

  • 修改后的回调 –

`

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

`

  • 新实例方法 –

`

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

`

  • 更新调查的脚本 –

`

 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 

`

它有点黑客但希望对你有用。

希望这是你正在寻找的。

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

对于您的第二个问题,我怀疑检查何时需要进行此计算会更好,最好是在网络流量处于低谷的指定时间批量处理。

编辑:Woops。 我实际上找到了2个链接但显然失去了第一个链接。 希望你能解决这个问题。

对于Rails 3 ActiveSupport::Callbacks为您提供必要的控制。 你可以reset_callbacks ,或者使用skip_callback来明智地禁用这样:

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

…之后您可以使用以下命令对Vote实例进行操作:add_points_to_user被禁止

不适用于Rails 5

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

适用于Rails 5

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

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