工厂女孩:如何在不创建新记录的情况下将一个记录与另一个记录关联?

时间:2021-01-11 10:40:34

I'm using Factory Girl/Rspec2/Rails 3.

我用的是工厂女孩/Rspec2/Rails 3。

In factories.rb, I have:

在工厂。rb,我:

Factory.define :user do |user|
  user.name       'Some guy'
  user.email      'some_guy@somewhere.org'
  user.password   'password'
end

Factory.define :org_admin, :parent => :user do |user|
  user.email 'org_admin@somehwere.org'
end

Factory.define :user_with_membership_request, :parent => :user do |user|
  user.email 'user_with_membership_request@somehwere.org'
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

and then in my rspec test I have:

在我的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

When I run the test, I get:

当我运行测试时,我得到:

 Failure/Error: @membership_request = Factory(:membership_request)
 Validation failed: Name has already been taken

I understand the reason for the failure is because FactoryGirl is creating another organization (with the same name).

我理解失败的原因是factory - girl正在创建另一个组织(名称相同)。

But what I'd like to do is create several memberships all associated with the same organization. How do I do that?

但是我想做的是创建几个与同一个组织相关的成员关系。我该怎么做呢?

Thanks.

谢谢。

Sean

肖恩

3 个解决方案

#1


18  

You could check for an existing organization and use it, or create one if none exists:

您可以检查并使用一个现有的组织,如果不存在的话,您可以创建一个:

Factory.define :membership do |membership|
  membership.user { Factory(:user) }
  membership.organization { Organization.first || Factory(:organization) }
end

FactoryGirl 4+ update:

FactoryGirl 4 +更新:

Factory.define do
  factory :membership do
    user { create(:user) }
    organization { Organization.first || create(:organization) }
  end
end

Another approach is to use unique identifiers (e.g.: names) for each factory that you want to reuse, then use initialize_with to generate it:

另一种方法是为要重用的每个工厂使用唯一标识符(例如:names),然后使用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

Now any reference to :organization_1 will always retrieve the same Organization. Obviously, you must use distinct names for this to work.

现在,任何对:organization_1的引用都将检索相同的组织。显然,必须使用不同的名称才能起作用。

#2


4  

There are two things. 1. You might still want to create unique names for Factory(:organisation) you can achieve that using Factory.sequence which will generate it uniquely for you. 2. You can pass in a Factory(:membership_request, :organization => @organization) to use the existing object instead of creating a new one.

有两件事。1。您可能仍然希望为Factory(:organisation)创建惟一的名称,您可以使用Factory实现这一点。序列,它将为你唯一地产生它。2。您可以通过工厂(:membership_request,:organization => @organization)来使用现有的对象,而不是创建新的对象。

#3


2  

With mongoid you can take combine the use of the #find_or_create_by method with Factory.attributes_for and do something like this

使用mongoid,您可以将#find_or_create_by方法与Factory结合使用。attributes_for这样做

factory :membership do
    organization { Organization.find_or_create_by(Factory.attributes_for(:organization))}
end

I'm sure ActiveRecord has something similar.

我相信ActiveRecord也有类似的功能。

#1


18  

You could check for an existing organization and use it, or create one if none exists:

您可以检查并使用一个现有的组织,如果不存在的话,您可以创建一个:

Factory.define :membership do |membership|
  membership.user { Factory(:user) }
  membership.organization { Organization.first || Factory(:organization) }
end

FactoryGirl 4+ update:

FactoryGirl 4 +更新:

Factory.define do
  factory :membership do
    user { create(:user) }
    organization { Organization.first || create(:organization) }
  end
end

Another approach is to use unique identifiers (e.g.: names) for each factory that you want to reuse, then use initialize_with to generate it:

另一种方法是为要重用的每个工厂使用唯一标识符(例如:names),然后使用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

Now any reference to :organization_1 will always retrieve the same Organization. Obviously, you must use distinct names for this to work.

现在,任何对:organization_1的引用都将检索相同的组织。显然,必须使用不同的名称才能起作用。

#2


4  

There are two things. 1. You might still want to create unique names for Factory(:organisation) you can achieve that using Factory.sequence which will generate it uniquely for you. 2. You can pass in a Factory(:membership_request, :organization => @organization) to use the existing object instead of creating a new one.

有两件事。1。您可能仍然希望为Factory(:organisation)创建惟一的名称,您可以使用Factory实现这一点。序列,它将为你唯一地产生它。2。您可以通过工厂(:membership_request,:organization => @organization)来使用现有的对象,而不是创建新的对象。

#3


2  

With mongoid you can take combine the use of the #find_or_create_by method with Factory.attributes_for and do something like this

使用mongoid,您可以将#find_or_create_by方法与Factory结合使用。attributes_for这样做

factory :membership do
    organization { Organization.find_or_create_by(Factory.attributes_for(:organization))}
end

I'm sure ActiveRecord has something similar.

我相信ActiveRecord也有类似的功能。