2011-04-01 72 views
20

如何创建同一班级的多个记录或多个工厂?如何在Factory Girl中创建/构建工厂的多个实例?

我想:

Factory.define :user do |user| 
    user.email "[email protected]" 
    user.password "somepassword" 

    user.email "[email protected]" 
    user.password "somepassword" 
end 

Factory.define :user do |user| 
    user.email "[email protected]" 
    user.password "somepassword" 
end 

Factory.define :user do |user| 
    user.email "[email protected]" 
    user.password "somepassword" 
end 

但它不工作 - Attribute already defined: email

回答

19

使用工厂有两个步骤,第一步是定义它们,第二步是使用它们。

1)定义它们:

Factory.define :user do |u| 
    u.sequence(:email) { |n| "mike#{n}@awesome.com"} 
    u.password "password123" 
end 

2)使用它们:

一个例子是使用它们的规格:

@user1 = Factory(:user) #has an email of [email protected] 
@user2 = Factory(:user) # has an email of [email protected] due to sequences in FG 

我看这个Railscast到对它有更好的感觉。

+0

非常感谢,我接受你的答案在几分钟内! ;) – benoitr 2011-04-01 06:25:42

+0

好运@benoitr! – 2011-04-01 06:26:14

39

这是一个老问题和答案,但它是第一个结果,我在谷歌找到,所以我想我要补充从docs下面的标题下,建筑物或创建多个记录

created_users = FactoryGirl.create_list(:user, 25) #creates 25 users 

twenty_year_olds = FactoryGirl.build_list(:user, 25, date_of_birth: 20.years.ago) #builds 25 users, sets their date_of_birth 

在我刚刚引用的例子中,每个用户都有不同的用户名,前提是在工厂定义中使用了sequence(请参阅Mike Lewis上面的答案)。

+0

太棒了!感谢您回到一个老问题并给出最新的答案。 – 2016-02-20 21:30:58

26

如果您希望来自同一(基地)工厂的记录具有不同的值,有几个选项。定义

A)覆盖属性

factory :post, aliases: [:approved_post] do 
    title "A title" 
    approved true 
end 

approved_post = create(:approved_post) 
unapproved_post = create(:post, approved: false) 

B)继承

factory :post do 
    title "A title" 

    factory :approved_post do 
    approved true 
    end 

    factory :unapproved_post do 
    approved false 
    end 
end 

approved_post = create(:approved_post) 
unapproved_post = create(:unapproved_post) 

C)序列

factory :user do 
    sequence(:email, 1000) { |n| "person#{n}@example.com" } 
end 

d)性状

factory :post do 
    title "My awesome title" 

    trait(:approved) { approved true } 

    trait(:unapproved) { approved false } 

    trait :with_comments do 
    after(:create) do |instance| 
     create_list :comment, 2, post: instance 
    end 
    end 

    factory :approved_post_with_comments, traits: [:approved, :with_comments] 
end 

approved_post_with_comments = create(:approved_post_with_comments) 
unapproved_post_with_no_comments = create(:post, :unapproved, title: "Test") 
post_with_title = build(:post) 

这些方法可以进行组合。这个例子使用列表和序列对并重写。

factory :user do 
    sequence(:username) { |n| "user#{n}" } 
    date_of_birth Date.today 
end 

# Build a pair and a list of users. 
two_newborns  = build_pair(:user) 
ten_young_adults = build_list(:user, 10, date_of_birth: 20.years.ago) 

# Create a pair and a list of users. 
two_young_adults = create_pair(:user, date_of_birth: 20.years.ago) 
ten_newborns  = create_list(:user, 10) 

我更喜欢尽可能使用特质,我觉得它们很灵活。

0

与当前factory_girl_rails 4.6.0我有某种相关的问题,build(:model)总是返回对象的同一个实例。使用sequence(:name) ...没有解决这个问题。于是,我产生了一些假的(空)的特征是这样的:

FactoryGirl.define do 
    factory :model do 
    ... 
    # fake traits to urge factory_girl to always return a new instance: 
    (1..5).each {|n| trait "var#{n}".to_sym } 
    end 
end 

,然后调用build(:model, :var1), build(:model, :var2)...

相关问题