2011-05-17 250 views
10

我有2个工厂。 Beta_user和Beta_invite。基本上,在Beta_user可以有效保存之前,我必须创建一个Beta_invite条目。不幸的是,这些模型没有干净的关联,但他们确实共享一个电子邮件字段。工厂女生依赖工厂

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 

因此,在beta beta_user工厂中,我尝试使用after_build回调来创建beta_invite工厂。

然而,它似乎是行为异步或什么的。可能做了find_by_email取回?

如果我试试这个:

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

我得到一个失败,说明没有与用户电子邮件beta_invite的记录。

相反,如果我尝试:

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

我得到更好的结果。就好像调用.build方法并等待保存允许创建beta_invite工厂的时间一样。而不是直接调用Factory.create。该文档说,在调用Factory.create的情况下,after_build和after_create回调被调用。

任何帮助,非常感谢。

UPDATE:

所以我使用的用户模型做了before_validation调用来检查,如果有一个beta邀请的方法。如果我将此方法调用改为before_save。它工作正常。有什么我在看。 factory_girl何时运行after_buildafter_create回调与活动记录的before_validationbefore_save有关?

+1

您可以发布您的用户类?这个错误可能在验证中或者它们是如何设置的。你说他们没有干净的协会也是奇怪的B/C。你究竟是什么意思?显示您的模型代码将有所帮助。 – 2011-05-21 22:28:31

回答

11

对我来说,它似乎只是应该能够工作,但我也有与工厂女孩协会的问题以及。我喜欢在这样的情况下使用的一种方法,如果关系不那么明显,是定义一个特殊的方法,你的工厂内,如下所示:

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

,并使用在测试中,只写

Factory.create_beta_user 

希望这会有所帮助。

+0

这就是我所要做的 – corroded 2011-05-25 05:51:53

6

不知道这是否会帮助你,但是这是我使用的代码:

# 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

这个解决方案对FactoryGirl来说更具惯用性 – JStroop 2014-01-17 20:10:18