2012-09-07 10 views
6

Ho avuto problemi a provare a creare fabbriche per alcuni oggetti e associazioni che ho definito nel mio progetto. Ho un tipo di associazione ciclica, in cui un oggetto è associato con altri due oggetti che poi si uniscono.Come posso creare fabbriche per un'associazione ciclica in FactoryGirl?

+--------------+   +-------------+ 
|    |   |    | 
| 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 

Fondamentalmente l'associazione divide in TestCase e si unisce nuovamente in TestDataValue, come ho potuto creare una fabbrica che apre e chiude il cerchio con gli stessi oggetti?

+1

Ne hai davvero bisogno? Nella maggior parte dei casi puoi prendere in giro e bloccare tutte quelle relazioni. È estremamente difficile mantenere fabbriche così complesse. – Sigurd

risposta

0

Questo non è testato, ma:

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 

Poi in specifiche:

@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

il problema con questo sarebbe quello: test_variable e: test_data_grid creerebbe diverse istanze di a: test_case se non mi sbaglio, e ho davvero bisogno che questo sia lo stesso oggetto. – bruno077

+0

Ho avuto domande simili su FactoryGirl sulla configurazione complessa del test. Ho risolto il problema chiamando ThoughtBot e acquistando un'ora del loro tempo. So che questo è insolito; Lo sto suggerendo qui perché a) ha funzionato per me, b) offri una grande taglia quindi suppongo che tu voglia una risposta di alta qualità presto, c) stai facendo una buona domanda. – joelparkerhenderson

0

Il mio suggerimento sarebbe quello di non configurarlo nelle fabbriche ma nelle prove stesse.

file di fabbrica (grazie a @ veritas1)

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 

file di test

@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 

So che potrebbe succhiare un po ', ma suona come il modo per farlo. Ad ogni modo, se stai lottando con i tuoi test, di solito è un segno che farai fatica con esso e dovresti ridisegnare le API. Non riesco a vedere un modo alternativo di farlo, ma potresti essere in grado di farlo con la conoscenza del dominio.

+0

Pensandoci, potresti semplicemente usare i callback. Dichiarare le associazioni come ha affermato @ veritas1, ma in fabbrica TestCase, utilizzare un callback dopo la creazione per impostare tutto come descritto in precedenza. https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#callbacks – FluffyJack

0

È possibile farlo manualmente:

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 

O scrivere qualche fabbrica aiutante:

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 case antenato come comune:

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 case antenato come comune e la stesso test_data_grid per ogni istanza:

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 
Problemi correlati