开发者

Factory Girl: How to associate a record to another record without creating a new record?

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

In factories.rb, I have:

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 'Mo开发者_开发技巧untain 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:

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

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

Thanks.

Sean


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:

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:

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.


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.


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

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

I'm sure ActiveRecord has something similar.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜