2012-09-07 10 views
6

Projemde tanımladığım bazı nesneler ve ilişkilendirmeler için fabrika oluşturmaya çalışırken sorun yaşıyorum. Bir nesnenin daha sonra bir araya geldiği iki nesne ile ilişkilendirildiği döngüsel bir ilişki var.FactoryGirl'de döngüsel bir ilişki için fabrikaları nasıl oluşturabilirim?

+--------------+   +-------------+ 
|    |   |    | 
| TestCase  +---------> | TestDataGrid| 
|    |   |    | 
+------+-------+   +------+------+ 
     |       | 
     |       | 
     |       | 
     v       v 
+--------------+   +--------------+ 
|    |   |    | 
|    |   |    | 
| TestVariable |   | TestDataSet | 
|    |   |    | 
+------+-------+   +------+-------+ 
     |       | 
     |       | 
     |       | 
     |       | 
     |  +---------------+ | 
     |  |    | | 
     |  |    | | 
     +---> | TestDataValue |<---+ 
      |    | 
      +---------------+ 

class TestCase < ActiveRecord::Base 
    has_many :test_variables, dependent: :destroy 
    has_many :test_data_grids 
    #...omitted code... 
end 

class TestVariable < ActiveRecord::Base 
    belongs_to :test_case 
    has_many :test_data_values 
    #...omitted code... 
end 

class TestDataValue < ActiveRecord::Base 
    belongs_to :test_variable 
    belongs_to :test_data_set 
    #...omitted code... 
end 

class TestDataSet < ActiveRecord::Base 
    belongs_to :test_data_grid 
    has_many :test_data_values 
    #...omitted code... 
end 

class TestDataGrid < ActiveRecord::Base 
    belongs_to :test_case 
    has_many :test_data_sets 
    #...omitted code... 
end 

I açılır ve aynı nesneler ile daire kapatan bir fabrika oluşturmak nasıl Temel olarak, ilişkilendirme TestCase böler ve TestDataValue tekrar birleştirilmektedir? Bu test edilmemiştir

+1

Gerçekten buna ihtiyacınız var mı? Vakaların çoğunda tüm bu ilişkilerle dalga geçebilir ve saplayabilirsin. Bu karmaşık fabrikaları korumak son derece zordur. – Sigurd

cevap

0

ama: gözlük Sonra

FactoryGirl.define do 

factory :test_data_value do 
    test_data_set 
    test_variable 
    # attributes 
end 

factory :test_data_set do 
    test_data_grid 
    # attributes 
end 

factory :test_variable do 
    test_case 
    # attributes 
end 

factory :test_case do 
    # attributes 
end 

factory :test_data_grid do 
    test_case 
    # attributes 
end 
end 

:

@test_data_value = FactoryGirl.create(:test_data_value) 

@test_variable = @test_data_value.test_variable 
@test_data_set = @test_data_value.test_data_set 
+0

bununla ilgili problem şudur: test_variable ve: test_data_grid, farklı bir örnek oluşturur: test_case, yanılmıyorsam, ve aynı nesneye gerçekten ihtiyacım var. – bruno077

+0

Karmaşık test kurulumu hakkında benzer FactoryGirl sorularım vardı. ThoughtBot'u arayarak ve onların bir saatini satın alarak çözdüm. Bunun sıra dışı olduğunu biliyorum; Burada öneriyorum çünkü a) benim için çalıştı, b) büyük bir lütuf teklif ediyorsun, bu yüzden yakında en kaliteli bir cevap istiyorsun, ve c) iyi bir katı soru soruyorsun. – joelparkerhenderson

0

Benim önerim fabrikalarda ancak testlerde kendileri bunu kurulmamış olacaktır.

Fabrika dosyası (@ veritas1 sayesinde)

FactoryGirl.define do 

    factory :test_data_value do 
    # attributes 
    end 

    factory :test_data_set do 
    # attributes 
    end 

    factory :test_variable do 
    # attributes 
    end 

    factory :test_case do 
    # attributes 
    end 

    factory :test_data_grid do 
    # attributes 
    end 
end 

Testi dosyası

@test_case = FactoryGirl.create(:test_case) 
@test_data_grid = FactoryGirl.create(:test_case) 
@test_variable = FactoryGirl.create(:test_case) 
@test_data_set = FactoryGirl.create(:test_case) 
@test_data_value = FactoryGirl.create(:test_case) 
@test_case.test_data_grids << @test_data_grid 
@test_case.test_variables << @test_variable 
@test_data_grid.test_data_set << @test_data_set 
@test_variable.test_data_values << @test_data_value 
@test_data_set.test_data_values << @test_data_value 

Ben biraz emmek biliyorum, ama bunu yapmak için bir yol gibi geliyor. Ancak bir düşünce olarak, eğer testlerinizle uğraşırsanız, genellikle iz ile mücadele edeceğiniz ve API'leri yeniden tasarlamanız gereken bir işarettir. Bunu yapmanın alternatif bir yolunu göremiyorum, ancak alanın bilgisi ile mümkün olabilir.

test_case = FactoryGirl.build(:test_case) 

test = FactoryGirl.build(:test_data_value, 
    :test_variable => FactoryGirl.build(:test_variable, 
    :test_case => test_case 
), 
    :test_data_set => FactoryGirl.build(:test_data_set, 
    :test_data_grid => FactoryGirl.build(:test_data_grid, 
     :test_case => test_case 
    ) 
) 
) 

test.test_variable.test_case == test.test_data_set.test_data_grid.test_case 
# => true 

Veya bazı yardımcı fabrika yazma:

+0

Bunu düşünürseniz, sadece geri aramaları kullanabilirsiniz. İlişkilendirmeleri @ veritas1 olarak belirtin, ancak TestCase fabrikasında, daha önce anlattığımma benzer her şeyi kurmak için bir geri arama oluşturduktan sonra kullanın. https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#callbacks – FluffyJack

0

elle yapabilir

FactoryGirl.define do 
    factory :test_data_value do 
    ignore do 
     test_case nil 
     test_data_grid nil 
    end 

    test_variable do 
     build :test_variable, 
     :test_case => test_case 
         || test_data_grid.try(:test_case) 
         || build(:test_case) 
    end 

    test_data_set do 
     build :test_data_set, :test_data_grid => test_data_grid || (
     build :test_data_grid, :test_case => test_case || build(:test_case) 
    ) 
    end 
    end 
end 

Test durumda gibi ortak atası:

test = FactoryGirl.create :test_data_value, 
    :test_case => FactoryGirl.build(:test_case) 

test.test_variable.test_case == test.test_data_set.test_data_grid.test_case 
# => true 

Test durumda gibi ortak atası ve her örnek için aynı test_data_grid:

test_data_grid = FactoryGirl.build :test_data_grid, 
    :test_case => FactoryGirl.build(:test_case) 

test = FactoryGirl.create :test_data_value, 
    :test_data_grid => test_data_grid 

test.test_variable.test_case == test.test_data_set.test_data_grid.test_case 
# => true