at.*_*at. 24 activerecord ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2 rails-activerecord
我需要在Rails中保存模型时计算值.所以我称之为calculate_averages
一个Survey
类的回调:
before_save :calculate_averages
Run Code Online (Sandbox Code Playgroud)
但是,偶尔(最初我有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
Run Code Online (Sandbox Code Playgroud)
在运行这段代码之前,我担心calculate_averages
它会被调用并复制它,甚至可能会导致我正在做的事情出现问题.好吧,那么我想,好吧,我只是什么也不做,让我们calculate_averages
打电话来做它的事.问题是,首先,即使您没有对记录进行任何更改,有没有办法强制回调被调用?
其次,平均的方式计算这是远远更有效率根本就没有让回调被调用的一切,做的一切平均值的一次.这可能不会让回调被调用吗?
vee*_*vee 23
我相信你所要求的是可以实现的ActiveSupport::Callbacks
.看看set_callback
和skip_callback
.
为了"即使您没有对记录进行任何更改也强制调用回调",您需要将回调注册到某个事件,例如save, validate etc.
.
set_callback :save, :before, :my_before_save_callback
Run Code Online (Sandbox Code Playgroud)
要跳过before_save
回调,您可以:
Survey.skip_callback(:save, :before, :calculate_average).
Run Code Online (Sandbox Code Playgroud)
请参考ActiveSupport::Callbacks
其他支持的选项链接,例如条件和块set_callback
和skip_callback
.
raf*_*ch2 15
要禁用en-mass回调,请使用...
Survey.skip_callback(:save, :before, :calculate_averages)
Run Code Online (Sandbox Code Playgroud)
然后启用它们......
Survey.set_callback(:save, :before, :calculate_average)
Run Code Online (Sandbox Code Playgroud)
这会跳过/设置所有实例.
dan*_*987 13
不适用于 Rails 5
Survey.skip_callback(:save, :before, :calculate_average)
Run Code Online (Sandbox Code Playgroud)
适用于 Rails 5
Survey.skip_callback(:save, :before, :calculate_average, raise: false)
Run Code Online (Sandbox Code Playgroud)
https://github.com/thoughtbot/factory_bot/issues/931
Ahm*_*ain 12
update_column
是一个ActiveRecord
不运行任何回调的函数,它也不运行验证.
如果您想在检查每个调查后有条件地跳过回调,您可以编写自定义方法。
例如。
修改回调
before_save :calculate_averages, if: Proc.new{ |survey| !survey.skip_callback }
Run Code Online (Sandbox Code Playgroud)
新实例方法
def skip_callback(value = false)
@skip_callback = @skip_callback ? @skip_callback : value
end
Run Code Online (Sandbox Code Playgroud)
用于更新调查的脚本
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
Run Code Online (Sandbox Code Playgroud)
它有点黑客,但希望对你有用。
希望这就是您正在寻找的。
对于你的第二个问题,我怀疑最好检查一下何时需要进行此计算,如果可以在网络流量处于低谷的指定时间批量处理,那就最好了。
编辑:哎呀。我实际上找到了 2 个链接,但显然丢失了第一个链接。希望你已经修好了。