Зависимые фабрики в Factory Девушка

У меня есть 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_user factory я пытаюсь использовать обратный вызов after_build для создания бета-версии factory.

Однако это похоже на асинхронное действие или что-то в этом роде. Возможно, вы выбрали find_by_email?

Если я попробую это:

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

Я получаю отказ, заявляя, что нет записи о бета-версии с этим электронным письмом пользователей.

Если я попробую:

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

Я получаю лучшие результаты. Как будто вызов метода .build и ожидание сохранения позволяет создавать бета-версию factory. Вместо прямого вызова factory.create. Документы говорят, что в случае вызова factory.create вызываются вызовы after_build и after_create.

Любая помощь очень ценится.

UPDATE:

Таким образом, модель User, которую я использую, вызывает вызов before_validation к методу, который проверяет, есть ли бета-приглашение. Если я переведу этот вызов метода на before_save. Он работает правильно. Есть что-то, над чем я смотрю. Когда factory_girl запускает обратные вызовы after_build и after_create по отношению к активной записи before_validation и before_save?

Ответ 1

Мне кажется, что он просто должен работать, но у меня были проблемы с ассоциациями в Factory -girl. Подход, который мне нравится использовать в таком случае, если отношения менее очевидны, заключается в определении специального метода внутри вашего factory следующим образом:

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

Надеюсь, что это поможет.

Ответ 2

Не уверен, что это поможет вам, но это код, который я использовал:

# 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