2012-06-01 12 views
10

Soy nuevo en FactoryGirl y estoy intentando el siguiente escenario simple?Factory Girl crear asociación con el objeto existente

factory :female, :class => Gender do 
    code 'Female' 
end 

factory :male, :class => Gender do 
    code 'Male' 
end 

factory :papas, :class => Customer do 
    first_name 'Jim' 
    last_name 'Papas' 
    association :gender, :factory => :male, :strategy => :build 
end 

factory :dumas, :class => Customer do 
    first_name 'Mary' 
    last_name 'Dumas' 
    association :gender, :factory => :female, :strategy => :build 
end 

Luego, en mi prueba:

create(:male) 
create(:female) 
create(:papas) 
create(:dumas) 

Tenga en cuenta que la clase de atención al cliente tiene un assocation belongs_toGender clase y una regla de validación que dice que gender_id debe estar presente. También tengo una validación en la clase Gender por singularidad en el código.

En create(:papas) declaración anterior, en mi prueba, me sale el error de que el Customer que se va a crear no es válido, porque es gender_idnil.

Si quito la asociación :strategy => :build en Customer:papas fábrica con el género, entonces voy a tener un error, que al intentar crear :papas, el código para el género ya existe.

¿Qué debo hacer para que mis pruebas creen los datos como se requiere arriba?

Tenga en cuenta que quiero tener géneros creados también sin clientes, en otras pruebas. No me diga que cree clientes con los comandos de creación de fábrica y deje que los clientes creen los géneros al mismo tiempo. Esto no funcionará si intento crear dos clientes del mismo género también.

Además, tiene que haber una respuesta mejor que la que:

@male = create(:male) 
@female = create(:female) 
create(:papas, :gender => @male) 
create(:dumas, :gender => @female) 

(.? Al utilizar accesorios de estas cosas estaban listas fuera de la caja tornaré de nuevo a los accesorios)

Respuesta

14

Puede lograr lo que quiere al no usar una fábrica para sus instancias de género y usar devoluciones de llamada en su fábrica de clientes.

No está obteniendo mucho de la fábrica de Gender tal como está (aunque agradezco que pueda simplificarse a los fines de hacer esta pregunta). Se podía hacer tan fácilmente esto para obtener un género:

Gender.find_or_create_by_code!('Male') 

Luego, en su fábrica de atención al cliente pueda utilizar un antes de devolución de llamada para establecer el Género:

factory :dumas, :class => Customer do 
    first_name 'Mary' 
    last_name 'Dumas' 
    before_create do |customer| 
    customer.gender = Gender.find_or_create_by_code!('Female') 
    end 
end 

El formato para el uso de las devoluciones de llamada en factory_girl tiene recientemente cambiado por lo que si usted está utilizando 3.3 o posterior tendrá que hacer:

before(:create) do |customer| 

en lugar de before_create.

Si la creación de un género es más compleja que su ejemplo, puede crear los géneros utilizando una fábrica pero conectarlos con sus clientes utilizando devoluciones de llamada usando find_by_code! insteand de find_or_create_by_code!.

+0

Aunque son bastante detallados frente a los accesorios, su respuesta es correcta. He estado usando factory girl los últimos dos meses y todavía mi próximo proyecto será con accesorios. –

+1

La ventaja que puede encontrar con las fábricas es si necesita crear muchos clientes diferentes. Puede tener una fábrica de male_customer y de female_customer y usarlas como las fábricas principales para sus diferentes clientes, lo que reduce la verbosidad considerablemente. Me alegro de que funcionó bien! – Shadwell

5

El bloque ignore puede usarse para terminar con esto, así:

factory :dumas, :class => Customer do 
    ignore do 
    female { Gender.find_by_code('Female') || create(:female) } 
    end 

    first_name 'Mary' 
    last_name 'Dumas' 
    gender { female } 
end 
5

ignore está en desuso y se eliminará en la versión 5 de Factory Girl.

su lugar, puede utilizar transient attributes:

factory :dumas, :class => Customer do 
    transient do 
    female { Gender.find_by_code('Female') || create(:female) } 
    end 

    first_name 'Mary' 
    last_name 'Dumas' 
    gender { female } 
end 
Cuestiones relacionadas