2015-12-27 5 views
8

私の親クラスは、子によってコールバックにafter_saveのコールバックですべての子をロードしないことがあります。私はちょうど2つのことをチェックし、私はそれを実行しているテストを、持っているRailsアソシエーションが正しくロードされない

class Parent < ActiveRecord::Base 
    has_many :children 

    def update_something 
    # explained below 
    end 
end 

class Child < ActiveRecord::Base 
    belongs_to :parent 

    after_save :tell_parent_to_update 

    def tell_parent_to_update 
    parent.update_something 
    end 
end 

私は2つのモデルがあります。 parent.children.countおよびparent.children.length両方とも4でなければなりません。私は数が時々異なっていることを認識していますが、(私が知っている限り)ここにはいけません。

私はちょうどchildrenを反復するためupdate_somethingを定義する場合:

def update_something 
    children.each do |child| 
    end 
end 

テストが失敗した - ループが1回実行されます(単一子の配列を返します - 作成最初child) 。

そうでなければ、childrenと言わない限り、私はどんなコードでも入力できます。子供たちへの呼び出しが、連合に間違ったことをロードさせているようなものです。

それリロード修正を強制:

def update_something 
    children(true).each do |child| 
    end 
end 

が、これはハックされ、可能であれば私はむしろルートの問題を修正します。

これは私のバグかレールバグですか(もしあれば、これを回避するために何かできますか?)

これは問題ではありませんが、これはsqlite3を使用したテスト環境です。単一のdevコンソールセッションでレコードを作成してテストすると、dev環境でも失敗します。

+0

'children.each do | child |'または 'Children.each do | child |'ですか? –

+0

多分何かキーワードと関係があるかもしれません。 – Nithin

+0

私は最初はそうだと思っていましたが、実際のコードでは今は非常に隔離されており、モデル/メソッドの実際の名前はドメイン固有であり、残念なことにキーワードではありません –

答えて

3

暗闇の中で刺していますが、私は、同じメモリブロックに格納関連オブジェクトと信じinverse_ofを、必要になることがあり、異なるブロックとは対照的に、標準的なアプローチは、作成します。私自身で

#app/models/parent.rb 
class Parent < ActiveRecord::Base 
    has_many :children, inverse_of: :parent 
    ... 
end 

#app/models/child.rb 
class Child < ActiveRecord::Base 
    belongs_to :parent, inverse_of: :children 
    ... 
end 

を経験、私はinverse_ofが他のモデルの連想データを呼び出すことができますが見つかりました。たとえば、parent.update_somethinginverse_ofなしで呼び出すと、エラーが発生するか(parentが明示的に定義されていない場合)、またはparentオブジェクトを再度構築する必要があります。

good write-up hereがあります。

-

それが解決しない場合、私は答えを削除します。

+0

残念ながら、それを修正していないようでした。書込みと私がオンラインで見つけたことによると、4.1のレール(私は4.2です)では自動的にそれを処理しています。将来、誰かのために修正する場合は、この回答を残しておくと便利です。 –

+0

申し訳ありませんが、ヘッドアップのおかげで。私は後世のためにそれを残すよ! –

0

これはおそらく、親の子がtell_parent_to_updateが実行される前にコードのある時点で熱心に読み込まれているためです。

parent.children.countはSQLクエリを実行し、DBに存在する子の数を返しますが、parent.children.lengthは子配列の長さを返すことになります(おそらくすでに読み込み中です)。

手動で1つの子供オブジェクトをレールコンソールから保存し、update_somethingの子の長さと数が同じかどうかを確認することをお勧めします。そうであれば、その前にあるコードが原因でテストに失敗している可能性があります。

関連する問題