工厂女孩的独立工厂

时间:2011-05-17 01:06:32

标签: ruby-on-rails activerecord rspec factory-bot

我有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 fetch?

如果我试试这个:

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回调。

非常感谢任何帮助。

更新

因此,我正在使用的用户模型对该方法进行before_validation调用,以检查是否存在测试版邀请。如果我将此方法调用移至before_save。它工作正常。有什么我在看的东西。 factory_girl何时运行与活动记录after_buildafter_create相关的before_validationbefore_save回调?

3 个答案:

答案 0 :(得分:11)

对我来说,它似乎应该能够工作,但我也遇到了Factory-girl中的关联问题。我喜欢在这种情况下使用的方法,如果关系不太明显,就是在工厂内部定义一个特殊方法,如下所示:

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

希望这有帮助。

答案 1 :(得分: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

答案 2 :(得分:0)

我发现 this 评论给出了一个很好的例子:

term = create(:term)
period = create(:period, term: term)
candidate = create(:candidate, term: term)

我将其应用于我的情况并且可以确认它有效。