2012-03-14 11 views
2

モデル "ワン"ActiveRecordモデルの二重保存を避けるには?

class One < ActiveRecord::Base 
    before_save :do_stuff 

    private 
    def do_stuff 
     two = Two.find(8) 
     two.field2 = 'Value' 
     two.save! 
    end 
end 

モデル "二" の実行

class Two < ActiveRecord::Base 
    before_save :do_stuff 

    private 
    def do_stuff 
     one = One.find(7) 
     one.field2 = 'SomeValue' 
     one.save! 
    end 
end 

two = Two.find(1) 
two.somefield = 'NewVal' 
two.save! 

無限ループが開始されます。 before_saveコールバックでお互いに変わらなければならない2つのモデルを実装するのに、ほとんどのルビー・オン・レール方法はありますか?

+0

ここで達成しようとしているのは正確ですか? –

+2

確かにあなたは現在の質問を解決する場合でも、デザインに問題があります。これは次の問題につながります – megas

+0

+1これはデザインの欠如のように見えますが、私はこの種の_cycleで自分自身を何度も見つけましたコールバック参照hell_。 [アドホックコールバックを避ける]可能性を持つのに役立つかもしれない(http://stackoverflow.com/questions/632742/how-can-i-avoid-running-activerecord-callbacks) – fguillen

答えて

2

、あなたはattr_accessorを使用してbefore_saveフィルタを無効にしたり、ループを避けるためにafter_saveブロックに移動する場合があります。あなたがそれらの少なくとも1つ上のトリガを無効にしたい

class One < ActiveRecord::Base 
    attr_accessor :not_doing_stuff 
    before_save :do_stuff, 
    :unless => :not_doing_stuff 

private 
    def do_stuff 
    two = Two.find(8) 
    two.field2 = 'Value' 
    two.save! 
    end 
end 

:このような

class Two < ActiveRecord::Base 
    before_save :do_stuff 

private 
    def do_stuff 
    one = One.find(7) 
    one.not_doing_stuff = true 
    one.field2 = 'SomeValue' 
    one.save! 
    end 
end 

物事は常に非常に醜いですので、試してみて、あなたができない限り、それを避ける例えば

他の方法は考えないでください。必要な場合は、いくつかのエッジケースでエンドレスループにロックされないように、十分な単体テストを書いていることを確認してください。

+0

非常に賢い..好きです! :) – fguillen

1

before_saveでsaveを呼び出しないでください:無限ループが発生します。 trueまたはfalseを代わりに返します。before_saveに入れたものがすべて成功した場合はtrue、失敗した場合はfalseを返します。 falseを返すと、保存と他のすべてのコールバックがキャンセルされます。あなたがこれを行う必要があり、できればまれに

関連する問題