工厂女孩的独立工厂

kev*_*ler 10 activerecord rspec ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

所以在beta beta_user工厂中我试图使用after_build回调来创建beta_invite工厂.

然而,它似乎是异步或其他东西.可能会执行find_by_email获取?

如果我试试这个:

Factory(:beta_user)
Factory(:beta_user)
Factory(:beta_user)
Run Code Online (Sandbox Code Playgroud)

我得到一个失败声明,没有用户发送电子邮件的beta_invite记录.

如果相反,我尝试:

Factory.build(:beta_user).save
Factory.build(:beta_user).save
Factory.build(:beta_user).save
Run Code Online (Sandbox Code Playgroud)

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

任何帮助深表感谢.

更新:

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

nat*_*vda 11

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

def Factory.create_beta_user
  beta_invite = Factory(:beta_invite)
  beta_user = Factory(:user, :email => beta_invite.email)
  beta_user
end
Run Code Online (Sandbox Code Playgroud)

并在你的测试中使用它,只需写

Factory.create_beta_user
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


Car*_*oui 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
Run Code Online (Sandbox Code Playgroud)