2010-05-30 10 views
40

Tengo un modelo Foo que tiene_muchas 'Bar'. Tengo una factory_girl factory para cada uno de estos objetos. La fábrica de Bar tiene una asociación con Foo; creará una instancia de un Foo cuando cree la barra.Poblando una asociación con niños en factory_girl

Me gustaría una fábrica que crea un Foo que contiene una barra. Idealmente, este Bar se crearía a través de: la fábrica de barras y respetaría la estrategia de compilación (crear/construir) utilizada para crear el Foo.

Sé que podría llamar a la fábrica de barras y luego tomar la referencia Foo de la nueva barra. Me gustaría evitar esto; en mi caso de prueba, el objeto importante es Foo; llamar a la fábrica de Bar parece un poco tortuoso. Además, puedo ver la necesidad de un Foo con múltiples barras.

¿Esto es posible en factory_girl? ¿Cómo defines esta relación en el padre?

Respuesta

48

El Factory.after_ hooks parece ser la única manera de hacer esto con éxito. He descubierto una manera de mantener la estrategia de construcción sin duplicar código:

Factory.define :foo do |f| 
    f.name "A Foo" 
    f.after(:build) { |foo| 
    foo.bars << Factory.build(:bar, :foo => foo) 
    } 
    f.after(:create) { |foo| 
    foo.bars.each { |bar| bar.save! } 
    } 
end 

Los estados que documentationafter_build se llamará antes after_create si se utiliza la estrategia de acumulación :create. Si se usa :build, solo se llama a after_build, y todos están contentos.

También he creado una versión abstraída de aplicación general at this gist para mantener las cosas SECAS.

+2

perfecto - he estado rasgándome el pelo por esto. ¡Gracias! – recurser

+2

Es difícil de creer que esta es la mejor manera de hacerlo, pero todavía parece ser el caso. Up-votó esta respuesta. – spier

+0

¿Cómo usas tu versión principal? ¿Cuál es la mejor manera de incorporar eso en una aplicación de Rails? –

4

Usted puede utilizar el método association dos maneras:

Factory.define :foo do |f| 
    # ... 
    f.association :bar 
end 

Si esto no funciona, puede asociar manualmente utilizando una devolución de llamada. He aquí un ejemplo de una de mis aplicaciones:

Factory.define :live_raid do |raid| 
end 

Factory.define :live_raid_with_attendee, :parent => :live_raid do |raid| 
    raid.after_create { |r| Factory(:live_attendee, :live_raid => r) } 
end 
+1

La primera sintaxis hace un un desbordamiento de pila/recursividad infinita en mi código. La segunda sintaxis funciona maravillosamente, excepto que no obedece a la estrategia de compilación. –

3

factorygirl 4.3.0 está llamando save! en una asociación al llamar build en el objeto padre, que creo que no está destinado a ser el comportamiento correcto.

Después de excavar el código FactoryGirl, agregar strategy: :build a la definición de asociación en la fábrica parece ahora crear mi asociación sin llamar al save!.

2

Usando factory_girl-4.5.0, crear n objetos secundarios en una fábrica objeto padre

FactoryGirl.define do 
    factory :foo do 
    name "test"   

    after(:build) do |instance| 
     n.times { instance.bars << FactoryGirl.create(:bar) }   
    end 
    end 
end 
Cuestiones relacionadas