2011-05-17 13 views
10

Tengo 2 fábricas. Beta_user y Beta_invite. Básicamente, antes de que un Beta_user pueda guardar válidamente, tengo que crear una entrada de Beta_invite. Lamentablemente, estos modelos no tienen asociaciones limpias, pero sí comparten un campo de correo electrónico.Fábricas dependientes en Factory Girl

Factory.sequence :email do |n| 
    "email#{n}@factory.com" 
end 

#BetaInvite 
Factory.define :beta_invite do |f| 
    f.email {Factory.next(:email)} 
    f.approved false 
    f.source "web" 
end 

#User 
Factory.define :user do |f| 
    f.email {Factory.next(:email)} 
    f.password "password" 
end 


#User => BetaUser 
Factory.define :beta_user, :parent => :user do |f| 
    f.after_build do |user| 
    if BetaInvite.find_by_email(user.email).nil? 
     Factory(:beta_invite, :email => user.email) 
    end 
    end 
end 

Así que en la fábrica beta beta_user estoy tratando de utilizar la llamada after_build volver a crear la fábrica beta_invite.

Sin embargo, parece estar actuando asincronamente o algo así. ¿Posiblemente está haciendo la búsqueda de find_by_email?

Si intento esto:

Factory(:beta_user) 
Factory(:beta_user) 
Factory(:beta_user) 

me sale un error que indica que no hay registro de un beta_invite con que el correo electrónico a los usuarios.

Si en lugar Trato:

Factory.build(:beta_user).save 
Factory.build(:beta_user).save 
Factory.build(:beta_user).save 

puedo obtener mejores resultados. Como si llamar al método .build y esperar para guardar permite tiempo para que se cree la fábrica de beta_invite. En lugar de llamar a Factory.create directamente. Los documentos dicen que, en el caso de llamar a Factory.create, se invocan los callbacks after_build y after_create.

Cualquier ayuda es muy apreciada.

ACTUALIZACIÓN:

lo tanto, el modelo de usuario que estoy usando hace una llamada al método before_validation que comprueba si hay una beta invitar. Si muevo este método, llamo al before_save. Funciona correctamente Hay algo que estoy buscando. ¿Cuándo factory_girl ejecuta las devoluciones de llamada after_build y after_create en relación con el registro activo before_validation y before_save?

+1

Se puede publicar su clase de usuario? El error puede estar en las validaciones o en cómo están configuradas. También es curioso por que dijiste que no tienen asociaciones limpias. ¿Qué quieres decir con eso exactamente? Mostrar el código de su modelo ayudaría. –

Respuesta

11

Para mí, parece que debería poder funcionar, pero también he tenido problemas con asociaciones en Factory-girl. Un enfoque que me gusta usar en un caso como éste, si las relaciones son menos evidentes, es definir un método especial, dentro de su fábrica de la siguiente manera:

def Factory.create_beta_user 
    beta_invite = Factory(:beta_invite) 
    beta_user = Factory(:user, :email => beta_invite.email) 
    beta_user 
end 

y para el uso que en sus pruebas, acaba de escribir

Factory.create_beta_user 

Espero que esto ayude.

+0

esto es lo que yo también haría – corroded

6

No estoy seguro si esto ayudaría a usted, pero este es el código que utilicé:

# Create factories with Factory Girl 

FactoryGirl.define do 
    # Create a sequence of unique factory users 
    sequence(:email) { |n| "factoryusername+#{n}@example.com"} 

    factory :user do 
    email 
    password "factorypassword" 

    # Add factory user email to beta invite 
    after(:build) {|user| BetaInvite.create({:email => "#{user.email}"})} 
    end 
end 
+1

Esta solución es mucho más idiomática para FactoryGirl – JStroop

Cuestiones relacionadas