如何保存模型,而在Rails的运行回调

问题描述 投票:24回答:7

我需要保存在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得到打来电话,做它的事。问题有,第一,有没有办法迫使回调,如果你做出任何更改的记录进行报复叫什么?

其次,平均的方式计算它更有效地根本就没有让回调被调用的一切,做的一切平均值的一次。这可能不会让回调被调用?

ruby-on-rails ruby-on-rails-3 activerecord ruby-on-rails-3.2 rails-activerecord
7个回答
23
投票

我相信你问什么可以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_callback链接skip_callback


15
投票

要禁用EN-质量回调使用...

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

然后让他们...

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

此跳过/套所有实例。


10
投票

update_column是不运行任何回调的ActiveRecord功能,而且它也不会运行验证。


4
投票

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

对于前。

  • 修改callback-

`

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

`

它有点本事,但希望会为你工作。


4
投票

为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


2
投票

希望这是你在找什么。

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

对于你的第二个问题,我怀疑这将是更好的检查时,这种计算需要发生,那将是最好的,如果它可以在批量在指定的时间,其中的网络流量是在谷底处理。

编辑:Woops。我居然发现2个链接,但失去了第一个,显然。希望你把它修好。


2
投票

为Rails 3 ActiveSupport::Callbacks为您提供了必要的控制。您可以reset_callbacks EN-集体,或使用skip_callback明智地禁止这样的:

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

......之后,你可以投票情况与:add_points_to_user操作抑制


1
投票

Rails的5.2.3要求当事人脚本后,以不触发模型事件,update_column(列,值)的伎俩:

task.update_column(task_status, ReferenceDatum::KEY_COMPLETED)

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

© www.soinside.com 2019 - 2024. All rights reserved.