6

コールバックを頻繁に使用するRailsアプリケーションがあります。そのため、複数のモデルで:after_createと:after_commitが呼び出される関数がかなりあります。

今のやり方が一番いいのかな。

基本的に、次のシナリオがあります。

Class Parent < ActiveRecord::Base

has_many :children


after_create :first_function 
after_commit :last_function

    def first_function
        if !self.processed?
            self.children.create(:name => "Richard The Lion Heart")
            self.processed = true
            self.save!
        end
    end

    def last_function
        if self.processed?
            if !self.processing?
                self.process
                                    self.save!
                self.processing = true
                self.save!
            end
        end
    end

end

したがって、モデルが更新されるたびにsecond_functionが呼び出され、関数自体によって更新される可能性があるため、関数が繰り返し呼び出されるため、全体が奇妙なデュアルブールチェックに依存していることがわかります。

全体として、コールバックを開始するたびに新しいブールチェックを導入する必要がある場合につながります。それは機能しますが、私はそれがエレガントだとは思いません。私は何が欠けていますか?

4

1 に答える 1

6

そのコードを書き直すことができるはずです -- このようなものですか? もちろん、実際のコードにはおそらくさらに複雑な部分があります。また、このコードはテストされていません。

Class Parent < ActiveRecord::Base
  has_many :children

  # only called when a new record is created
  after_create :first_function 

  # only called for updates, not new records, should still be inside the current transaction
  after_update :last_function

  private
    def first_function
      self.children.create(:name => "Richard The Lion Heart")
      # don't call save in here, already in a transaction
    end

    def last_function
      self.process
      # don't call save in here, already in a transaction        
    end

    def process
      # doing stuff ....
      self.children[0].update_attribute(:name, "Beowulf")
    end
end    

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

これは合計 12 のコールバックであり、Active Record ライフサイクルの各状態に反応して準備するための計り知れない力を提供します。既存のレコードに対して Base#save を呼び出すシーケンスは似ていますが、各 _create コールバックが対応する _update コールバックに置き換えられる点が異なります。

利用方法

p = Parent.new(:foo => "bar")
p.save
p.children[0].name
# => "Richard The Lion Heart"

p.update_attributes(:baz => "fud")
p.children[0].name
# => Beowulf

Rails コンソールからの ActiveRecord コールバック (awesome_print ap を使用)

> ap ActiveRecord::Callbacks::CALLBACKS
[
  [ 0] :after_initialize,
  [ 1] :after_find,
  [ 2] :after_touch,
  [ 3] :before_validation,
  [ 4] :after_validation,
  [ 5] :before_save,
  [ 6] :around_save,
  [ 7] :after_save,
  [ 8] :before_create,
  [ 9] :around_create,
  [10] :after_create,
  [11] :before_update,
  [12] :around_update,
  [13] :after_update,
  [14] :before_destroy,
  [15] :around_destroy,
  [16] :after_destroy,
  [17] :after_commit,
  [18] :after_rollback
]
于 2012-07-18T15:14:21.523 に答える