Зависимые фабрики в Factory Girl - PullRequest
10 голосов
/ 17 мая 2011

У меня есть 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 я пытаюсь использовать обратный вызов 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 метод, который проверяет, есть ли бета-приглашение. Если я переместу этот вызов метода на before_save вместо этого. Работает правильно. Есть что-то, на что я смотрю. Когда factory_girl выполняет обратные вызовы after_build и after_create относительно активных записей before_validation и before_save?

Ответы [ 2 ]

11 голосов
/ 20 мая 2011

Мне кажется, что он просто должен быть в состоянии работать, но у меня были проблемы с ассоциациями в 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

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

6 голосов
/ 17 сентября 2012

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

# 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
...