How to create/build multiple instances of a factory in Factory Girl?
How do I create multiple records or multiple factories of the same class?
I tried:
Factory.define :user do |user|
user.email "someuser@somesite.com"
user.password "somepassword"
user.email "another_existing_user@somesite.com"
user.password "somepassword"
end
and
Factory.define :user do |user|
user.email "someuser@somesite.com"
user.password "somepassword"
end
Factory.define :user do |user|
user.email "another_existing_user@somesite.com"
user.password "somepassword"
end
But it doesn't work -- Att开发者_如何学编程ribute already defined: email
.
This is an older question and answer but it was the first result I found on Google so I thought I would add the following from the docs under the heading Building or Creating Multiple Records:
created_users = FactoryBot.create_list(:user, 25) #creates 25 users
twenty_year_olds = FactoryBot.build_list(:user, 25, date_of_birth: 20.years.ago) #builds 25 users, sets their date_of_birth
If you want to run this in the rails console, consider the following answer here: https://stackoverflow.com/a/23580836/4880924
In the example I just cited, each user would have a different username, provided that sequence
is used in the factory definition (see Mike Lewis' answer above).
There's a couple of options if you want records from the same (base) factory to have different values.
A) Override defined attributes
factory :post, aliases: [:approved_post] do
title "A title"
approved true
end
approved_post = create(:approved_post)
unapproved_post = create(:post, approved: false)
B) Inheritance
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) Sequences
factory :user do
sequence(:email, 1000) { |n| "person#{n}@example.com" }
end
D) Traits
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)
These methods can be combined. This example uses lists and pairs with sequences and overriding.
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)
I prefer to use traits whenever possible, I find them flexible.
There are two steps to using Factories, the first is to define them, and the second is to use them.
1) Define Them:
Factory.define :user do |u|
u.sequence(:email) { |n| "mike#{n}@awesome.com"}
u.password "password123"
end
2) Using Them:
An example would be to use them in a spec:
@user1 = Factory(:user) #has an email of mike1@awesome.com
@user2 = Factory(:user) # has an email of mike2@awesome.com due to sequences in FG
I'd watch this Railscast to get a better feel for it.
With the current factory_girl_rails
4.6.0 I had the somehow related problem that build(:model)
returned always the same instance of the object. Using sequence(:name) ...
didn't fix that. So I generated some fake (empty) traits like this:
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
And then calling build(:model, :var1), build(:model, :var2)...
精彩评论