2017-01-04 7 views
2

a common race conditionを避けるためにコミット後に実行する必要があるサイドキーグジョブがあります。Railsのインライン `after_commit`コールバック

class User < ActiveRecord::Base 
    ... 
    after_commit do |user| 
    if @enqueue_some_job 
     SomeJob.new(user).enqueue 
     @enqueue_some_job = nil 
    end 
    end 

    def verify 
    @enqueue_some_job = ... 
    ... 
    save! 
    end 
end 

コードは少し醜いです。私は何とかこのようなコールバックをインラインでラップすることができ、むしろ多くをしたい:

class User < ActiveRecord::Base 
    def verify 
    if ... 
     run_after_commit do |user| 
     SomeJob.new(user).enqueue 
     end 
    end 
    ... 
    save! 
    end 
end 

はRailsのに組み込まれたものは、(それが一時的なインスタンス変数の設定に依存しない)、このような構文をサポートするために存在していますか?あるいは、Railsを拡張してこのような構文を追加するライブラリが存在しますか?

答えて

0

は懸念を経由して使用して解決策を見つけました。スニペットは十分に再利用され、インスタンス変数を抽象化して再利用可能なパターンを作成する方がよいでしょう。それは戻って(トランザクションがロールバックするために存在しないためafter_commit経由でサポートされているかわからないを処理しません。

アプリ/モデル/懸念/ callbackable.rb

module Callbackable 
    extend ActiveSupport::Concern 

    included do 

    after_commit do |resource| 
     if @_execute_after_commit 
     @_execute_after_commit.each do |callback| 
      callback.call(resource) 
     end 
     @_execute_after_commit = nil 
     end 
    end 
    end 

    def execute_after_commit(&callback) 
    if callback 
     @_execute_after_commit ||= [] 
     @_execute_after_commit << callback 
    end 
    end 

end 

アプリ/モデル/ user.rb

class User < ActiveRecord::Base 
    include Callbackable 

    def verify 
    if ... 
     execute_after_commit do |user| 
     SomeJob.new(user).enqueue 
     end 
    end 
    ... 
    save! 
    end 
end 
0

コールバックを宣言するときは、代わりにブロックのメソッド名を使用することができます。

class User < ActiveRecord::Base 
    after_commit :do_something! 

    def do_something! 
    end 
end 

あなたはifunlessオプションを使用することができますコールバックに条件を設定します。これらは単にキーワードではなくハッシュオプションであることに注意してください。

あなたはメソッド名やラムダを使用することができます。

class User < ActiveRecord::Base 
    after_commit :do_something!, if: -> { self.some_value > 2 } 
    after_commit :do_something!, unless: :something? 

    def do_something! 
    end 

    def something? 
    true || false 
    end 
end 
+0

:)それはあなたのお役に立てば幸いですので、私は、その後のインスタンス変数を設定する必要があるだろうそれらのそれぞれ。 –

+0

私はあなたが何を得ようとしているのか、本当にそれを思っているのか分かりません。 if節または 'if'オプションで直接' verify'メソッドを使うことができます。なぜ、あなたがブール条件に評価されるメソッドだけでなく、インスタンス変数/状態が必要だと思うのか分かりません。 – max

+0

また、コードの実行時にはやや混乱しているように見えます。クラスの評価時にコールバックが宣言されています。 2番目の例のverifyメソッドはインスタンスメソッドです。メタプログラミングを使ってインスタンスからシングルトンクラスを変更することができますが、これはあなたが望むものではない可能性が最も高いです。 – max

-1

は、作成した後に、ユーザを確認する必要があると仮定すると。

after_commit :run_sidekiq_job, on: :create 
after_commit :run_sidekiq_job, on: [:create, :update] // if you want on update as well. 

これにより、dbへのコミット後にのみジョブが実行されます。

次に、実行する必要があるジョブを定義します。関数内のライブチェックのため、残念ながら条件(同じ場合は `verify`) - -

def run_sidekiq_job 
    --------------- 
    --------------- 
end 

は感謝最大

関連する問題