5

私はこのタスクモデルを持っています:

class Task < ActiveRecord::Base
  acts_as_tree :order => 'sort_order'
end

そして、私はこのテストを持っています

class TaskTest < Test::Unit::TestCase
  def setup
    @root = create_root
  end

  def test_destroying_a_task_should_destroy_all_of_its_descendants
    d1 = create_task(:parent_id => @root.id, :sort_order => 2)
    d2 = create_task(:parent_id => d1.id, :sort_order => 3)
    d3 = create_task(:parent_id => d2.id, :sort_order => 4)
    d4 = create_task(:parent_id => d1.id, :sort_order => 5)
    assert_equal 5, Task.count

    d1.destroy

    assert_equal @root, Task.find(:first)
    assert_equal 1, Task.count
  end
end

テストは成功です。d1 を破棄すると、d1 のすべての子孫が破棄されます。したがって、破棄後はルートのみが残ります。

ただし、タスクに before_save コールバックを追加した後、このテストは失敗しています。これは私がタスクに追加したコードです:

before_save :update_descendants_if_necessary

def update_descendants_if_necessary
  handle_parent_id_change if self.parent_id_changed?
  return true
end

def handle_parent_id_change
  self.children.each do |sub_task|
    #the code within the loop is deliberately commented out
  end
end

このコードを追加すると、assert_equal 1, Task.count失敗し、Task.count == 4. ブロックをコメントアウトすると、テストが再びパスするため、self.children下が原因だと思います。handled_parent_id_changeself.children.each do |sub_task|

何か案は?

4

2 に答える 2

4

バグを見つけました。この線

d1 = create_task(:parent_id => @root.id, :sort_order => 2)

d1 を作成します。これはコールバックを呼び出し、before_saveコールバックは を呼び出しますself.children。Orion が指摘したように、これは d1 の子をキャッシュします。

ただし、この時点では、d1 にはまだ子がありません。したがって、d1 の子のキャッシュは空です。

したがって、d1 を破棄しようとすると、プログラムは d1 の子を破棄しようとします。キャッシュに遭遇し、それが空であることを発見し、結果は d2、d3、および d4 を破棄しません。

タスクの作成を次のように変更することでこれを解決しました。

@root.children << (d1 = new_task(:sort_order => 2))
@root.save!

これは機能したので、問題ありません:)これらの解決策は試していませんが、 d1( d1.reload)またはself.children( )をリロードすることでこれを修正することも可能だと思います。self.children(true)

于 2008-10-06T04:02:30.317 に答える
1

children 単純な has_many 関連付けです

つまり、 を呼び出すと.children、データベースからロードされます (まだ存在しない場合)。その後、それらをキャッシュします。

2 番目の「テスト」では、実際のデータベースではなくキャッシュされた値を実際に確認すると言っていましたがTask.countd1.children.count. うーん

ログを見ましたか?実行中のSQLが表示されます。そこに、何が起こっているかを示す mysql エラーが表示される場合があります。

于 2008-10-05T20:07:08.123 に答える