Railsでモデルを保存するときに値を計算する必要があります。だから私はcalculate_averages
Survey
クラスのコールバックとして:
before_save :calculate_averages
ただし、ときどき(この操作を必要とする1万件のレコードがある場合)、すべてのレコードのすべての平均を手動で更新する必要があります。問題ありません。次のようなコードがあります。
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
呼び出され、その処理を行います。問題は、まず、レコードに変更を加えなかった場合でも、コールバックを強制的に呼び出す方法がありますか?
第二に、平均値の計算方法farは、コールバックがまったく呼び出されないようにして、すべての平均値を一度に実行する方が効率的です。コールバックが呼び出されないようにすることは可能ですか?
あなたが求めていることは ActiveSupport::Callbacks
で達成できると信じています。 set_callback
とskip_callback
をご覧ください。
「レコードに変更を加えなくてもコールバックを強制的に呼び出す」ためには、コールバックを何らかのイベントに登録する必要があります。 save, validate etc.
。
set_callback :save, :before, :my_before_save_callback
before_save
コールバックをスキップするには、次のようにします。
Survey.skip_callback(:save, :before, :calculate_average).
ActiveSupport::Callbacks
およびset_callback
への条件やブロックなど、他のサポートされているオプションでリンクされた skip_callback
を参照してください。
一括コールバックを無効にするには...
Survey.skip_callback(:save, :before, :calculate_averages)
その後、それらを有効にするには...
Survey.set_callback(:save, :before, :calculate_average)
これにより、すべてのインスタンスがスキップ/設定されます。
update_column
は、コールバックを実行しないActiveRecord
関数であり、検証も実行しません。
各調査を確認した後に条件付きでコールバックをスキップする場合は、カスタムメソッドを記述できます。
例えば.
`
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
`
ちょっとしたハックですが、希望はあなたのために働くでしょう。
Rails 5では機能しません
Survey.skip_callback(:save, :before, :calculate_average)
Rails 5
Survey.skip_callback(:save, :before, :calculate_average, raise: false)
うまくいけば、これがあなたが探しているものです。
https://stackoverflow.com/a/6587546/2238259
2番目の問題については、この計算がいつ必要になるかを検査する方が良いと思われます。ネットワークトラフィックがトラフにある指定された時間にバッチで処理できれば最高です。
編集:うわー。実際に2つのリンクを見つけましたが、最初のリンクは失われたようです。うまくいけば、それが修正されます。
Rails 5.2.3では、モデルイベントをトリガーしないようにアフターパーティスクリプトが必要です。update_column(column_name、value)はトリックを行いました:
task.update_column(task_status, ReferenceDatum::KEY_COMPLETED)
https://apidock.com/Rails/ActiveRecord/Persistence/update_column