2012-06-01 3 views
10

Я новичок в FactoryGirl, и я пробую следующий простой сценарий?Factory Girl создает связь с существующим объектом

factory :female, :class => Gender do 
    code 'Female' 
end 

factory :male, :class => Gender do 
    code 'Male' 
end 

factory :papas, :class => Customer do 
    first_name 'Jim' 
    last_name 'Papas' 
    association :gender, :factory => :male, :strategy => :build 
end 

factory :dumas, :class => Customer do 
    first_name 'Mary' 
    last_name 'Dumas' 
    association :gender, :factory => :female, :strategy => :build 
end 

Тогда в моем тесте:

create(:male) 
create(:female) 
create(:papas) 
create(:dumas) 

Обратите внимание, что класс Customer имеет Assocation belongs_toGender класс и правила проверки, который говорит, что gender_id должен присутствовать. У меня также есть проверка на класс Gender для уникальности кода.

На create(:papas) выше утверждение, в моем тесте, я получаю ошибку, что Customer, который будет создан не является допустимым, поскольку gender_id является nil.

Если удалить :strategy => :build на Customer:papas фабрики ассоциации с полом, то я получаю сообщение об ошибке, что при попытке создать :papas, код для пола уже существует.

Что мне нужно сделать, чтобы мои тесты отображали данные, как требуется выше?

Обратите внимание, что я хочу, чтобы гендерные группы были созданы без клиентов, а также в других тестах. Не говорите мне, чтобы создавать клиентов с помощью команд создания фабрики и позволять клиентам создавать полы в одно и то же время. Это не сработает, если я попытаюсь создать двух клиентов одного пола.

Кроме того, там должен быть лучший ответ, чем один:

@male = create(:male) 
@female = create(:female) 
create(:papas, :gender => @male) 
create(:dumas, :gender => @female) 

(.? При использовании приборов эти вещи были готовы вне коробки Должен ли я вернуться обратно к светильникам)

ответ

14

Вы можете достичь того, чего хотите, не используя фабрику для своих экземпляров «Пол» и используя обратные вызовы на своей фабрике «Клиент».

Вы не набираете много от фабрики «Гендер» в ее нынешнем виде (хотя я ценю, что это может быть упрощено с целью задать этот вопрос). Вы можете так же легко сделать это, чтобы получить Пол:

Gender.find_or_create_by_code!('Male') 

Тогда в вашей фабрике клиента вы можете использовать до того обратного вызова, чтобы установить Пол:

factory :dumas, :class => Customer do 
    first_name 'Mary' 
    last_name 'Dumas' 
    before_create do |customer| 
    customer.gender = Gender.find_or_create_by_code!('Female') 
    end 
end 

Формат использования обратных вызовов в factory_girl имеет в последнее время изменилось, так что если вы используете 3.3 или более поздней версии вам нужно сделать:

before(:create) do |customer| 

вместо before_create.

Если создание пола более сложное, чем ваш пример, вы все равно можете создать гендерные группы с использованием фабрики, но подключите их к своим клиентам с помощью обратных вызовов, используя find_by_code! insteand find_or_create_by_code!.

+0

Хотя довольно громоздким против светильников, ваш ответ является правильным. Я использую заводскую девушку последние два месяца, и все же мой следующий проект будет с светильниками! –

+1

Преимущество, которое вы можете найти на фабриках, - это если вам нужно создать множество разных клиентов. У вас может быть фабрика male_customer и female_customer и использовать ее в качестве родительских фабрик для ваших разных клиентов, что значительно снижает значимость. Рад, что это сработало! – Shadwell

5

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

factory :dumas, :class => Customer do 
    ignore do 
    female { Gender.find_by_code('Female') || create(:female) } 
    end 

    first_name 'Mary' 
    last_name 'Dumas' 
    gender { female } 
end 
5

ignore устарел и будет удален на 5-е версии Factory Girl.

Вместо этого, вы можете использовать transient attributes:

factory :dumas, :class => Customer do 
    transient do 
    female { Gender.find_by_code('Female') || create(:female) } 
    end 

    first_name 'Mary' 
    last_name 'Dumas' 
    gender { female } 
end 
Смежные вопросы