2011-05-17 6 views
10

J'ai 2 usines. Beta_user et Beta_invite. Fondamentalement avant qu'un Beta_user puisse valablement sauvegarder je dois créer une entrée de Beta_invite. Malheureusement, ces modèles n'ont pas d'associations propres, mais ils partagent un champ de courrier électronique.Usines dépendantes dans 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 

Ainsi, dans l'usine de beta_user bêta Je suis en train d'utiliser l'appel after_build arrière pour créer l'usine de beta_invite.

Cependant, il semble agir async ou quelque chose. Peut-être faire le find_by_email fetch?

Si j'essaie ceci:

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

Je reçois un échec indiquant qu'il n'y a aucune trace d'un beta_invite avec cet e-mail des utilisateurs.

Si au contraire j'essayer:

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

pour obtenir de meilleurs résultats. Comme si l'appel de la méthode .build et l'attente de la sauvegarde permettait de créer l'usine beta_invite. Au lieu d'appeler Factory.create directement. Les docs disent que dans le cas d'appeler Factory.create, les callbacks after_build et after_create sont appelés.

Toute aide est très appréciée.

MISE À JOUR:

Ainsi, le modèle de l'utilisateur J'utilise-t un appel before_validation à la méthode qui vérifie s'il y a une invitation bêta. Si je déplace cette méthode, appelez before_save à la place. Cela fonctionne correctement. Y a-t-il quelque chose que je suis en train de regarder? Quand factory_girl exécute-t-il les rappels after_build et after_create par rapport aux enregistrements before_validation et before_save?

+1

Pouvez-vous poster votre classe utilisateur? Le bug peut être dans les validations ou comment ils sont mis en place. Aussi c'est bizarre b/c vous avez dit qu'ils n'ont pas d'associations propres. Que voulez-vous dire exactement par là? Montrer votre code de modèle aiderait. –

Répondre

11

Pour moi, il semble que ça devrait fonctionner, mais j'ai aussi eu des problèmes avec les associations dans Factory-girl. Une approche que je préfère utiliser dans un cas comme celui-ci, si les relations sont moins évidentes, est de définir une méthode spéciale, l'intérieur de votre usine comme suit:

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

et à utiliser que dans vos tests, il suffit d'écrire

Factory.create_beta_user 

Espérons que cela aide.

+0

c'est ce que je ferais aussi – corroded

6

Je ne sais pas si cela vous aider, mais c'est le code je:

# 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

Cette solution est beaucoup plus idiomatique à FactoryGirl – JStroop

Questions connexes