Factory Девушка: как связать запись с другой записью, не создавая новую запись?
Я использую Factory Girl/Rspec2/Rails 3.
В factories.rb у меня есть:
Factory.define :user do |user|
user.name 'Some guy'
user.email '[email protected]'
user.password 'password'
end
Factory.define :org_admin, :parent => :user do |user|
user.email '[email protected]'
end
Factory.define :user_with_membership_request, :parent => :user do |user|
user.email '[email protected]'
end
Factory.define :organization do |org|
org.name 'MEC'
org.description 'Mountain Equipment Co-op'
end
Factory.define :membership do |membership|
membership.user { Factory(:user) }
membership.organization { Factory(:organization) }
end
Factory.define :admin_membership, :parent => :membership do |membership|
membership.user { Factory(:org_admin) }
membership.is_admin true
membership.status 'active'
end
Factory.define :membership_request, :parent => :membership do |membership|
membership.user { Factory(:user_with_membership_request) }
membership.status 'requested'
end
а затем в моем тесте rspec у меня есть:
it 'should accept the membership request' do
@org_admin = Factory(:org_admin)
test_sign_in(@org_admin)
@organization = Factory(:organization)
@membership_request = Factory(:membership_request)
put :update, :organization_id => @organization.id, :id => @membership_request.id, :acceptance => 'approve'
...
end
Когда я запускаю тест, я получаю:
Failure/Error: @membership_request = Factory(:membership_request)
Validation failed: Name has already been taken
Насколько я понимаю, причиной отказа является то, что FactoryGirl создает другую организацию (с тем же именем).
Но то, что я хотел бы сделать, это создать несколько членов, связанных с одной и той же организацией. Как это сделать?
Спасибо.
Шон
Ответы
Ответ 1
Вы можете проверить существующую организацию и использовать ее или создать ее, если ее не существует:
Factory.define :membership do |membership|
membership.user { Factory(:user) }
membership.organization { Organization.first || Factory(:organization) }
end
Обновление FactoryGirl 4+:
Factory.define do
factory :membership do
user { create(:user) }
organization { Organization.first || create(:organization) }
end
end
Другой подход заключается в использовании уникальных идентификаторов (например, имен) для каждого factory, который вы хотите использовать повторно, а затем используйте initialize_with
для его создания:
factory :organization_1 do
ignore { organization_name 'Sample Organization 1' }
name { organization_name }
initialize_with { Organization.find_or_create_by_name(organization_name) }
end
Теперь любая ссылка на :organization_1
всегда будет получать тот же Organization
. Очевидно, что для этого нужно использовать разные имена.
Ответ 2
Есть две вещи.
1. Вы все равно можете создавать уникальные имена для Factory(:organisation)
, которые вы можете достичь, используя Factory.sequence
, который будет генерировать его уникально для вас.
2. Вы можете передать Factory(:membership_request, :organization => @organization)
для использования существующего объекта вместо создания нового.
Ответ 3
С помощью mongoid вы можете объединить использование метода #find_or_create_by с Factory.attributes_for и сделать что-то вроде этого
factory :membership do
organization { Organization.find_or_create_by(Factory.attributes_for(:organization))}
end
Я уверен, что у ActiveRecord есть что-то подобное.