在 Factory_girl 中使用时,Faker 产生重复数据

我想用 Faker gem 把一些假数据填充到一个工厂里:

Factory.define :user do |user|
user.first_name Faker::Name::first_name
user.last_name Faker::Name::last_name
user.sequence(:email) {|n| "user#{n}@blow.com" }
end

然而,尽管我预计这会产生不同的名字和姓氏的用户,但每个用户都是相同的:

>> Factory(:user)
=> #<User id: 16, email: "user7@blow.com", created_at: "2011-03-18 18:29:33",
updated_at: "2011-03-18 18:29:33", first_name: "Bailey", last_name: "Durgan">
>> Factory(:user)
=> #<User id: 17, email: "user8@blow.com", created_at: "2011-03-18 18:29:39",
updated_at: "2011-03-18 18:29:39", first_name: "Bailey", last_name: "Durgan">

如何让 Faker gem 为每个用户生成新名称,而不只是重用原始名称?

17969 次浏览
Factory.define :user do |user|
user.first_name { Faker::Name::first_name }
user.last_name { Faker::Name::last_name }
user.sequence(:email) {|n| "user#{n}@blow.com" }
end

Try putting brackets around the fakers. see this link

For the sake of preserving the correct answer, here it is translocated from the blog, I take no credit for the answer.

If you use the code below, faker will not churn out unique names

Factory.define :user do |u|
u.first_name Faker::Name.first_name
u.last_name Faker::Name.last_name
end

However putting curly braces around faker makes it work!

Factory.define :user do |u|
u.first_name { Faker::Name.first_name }
u.last_name { Faker::Name.last_name }
end

To explain why, the first example is producing the same names. It's only evaluating once. The second example evaluates every time the factory is used.

This is due to the {} providing lazy evaluation. Essentially they are providing a proc/lambda with the Faker call as their return value.

Note that Faker may still be providing duplicate data due to the limited amount of fake data available.

For simple testing purposes and to get by uniqueness validations, I've used the following:

sequence(:first_name) {|n| Faker::Name::first_name + " (#{n})"}
sequence(:last_name) {|n| Faker::Name::last_name + " (#{n})"}

A (less efficient) alternative to using sequences when you have a uniqueness validation on an attribute is to check whether a proposed value already exists and keep trying new ones until it's unique:

FactoryGirl.define do
factory :company do
name do
loop do
possible_name = Faker::Company.name
break possible_name unless Company.exists?(name: possible_name)
end
end
end
end