FactoryGirl + Faker - 在数据库种子数据中为每个对象生成相同的数据

38

我正在使用FactoryGirl和Faker在我的seeds.rb文件中生成用户对象,但由于电子邮件唯一性验证,同一个用户被创建了多次,导致rake db:seed失败。

用户的工厂代码:

#users.rb
require 'faker'

FactoryGirl.define do
  factory :user do
    first_name            Faker::Name.first_name
    last_name             Faker::Name.last_name
    phone                 Faker::PhoneNumber.cell_phone
    email                 Faker::Internet.email
    password              "password"
    password_confirmation "password"
  end
end

而且在 seeds.rb 文件中的代码:

#seeds.rb
rand(5..11).times { FactoryGirl.create(:user) }

错误:

ActiveRecord::RecordInvalid: 验证失败:Email已被使用

如果我打开控制台并使用FactoryGirl.create(:user),我会得到相同的结果... 即使我运行Faker::Internet.email多次,也会创建相同的对象。

FactoryGirl:

[1] pry(main)> FactoryGirl.create(:user)
...
=> #<User id: 3, first_name: "Osvaldo", last_name: "Wunsch", email: "willy@damore.net", phone: "(912)530-4949 x64848", created_at: "2014-07-31 20:57:27", updated_at: "2014-07-31 20:57:27", encrypted_password: "$2a$10$mxWC7yLYR0m/Sw8MO6Lyru.xuTHCdCEuM9Orx3LXGApF...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil>
[2] pry(main)> FactoryGirl.create(:user)
...
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken

仅使用Faker本身:

[3] pry(main)> Faker::Internet.email
=> "hobart_purdy@goodwinmills.org"
[4] pry(main)> Faker::Internet.email
=> "pierce_brekke@gislasonrolfson.net"
我在这里缺少什么?为什么每次使用FactoryGirl时,Faker都会生成相同的数据?

重复数据生成问题 - 当在Factory Girl中使用Faker时,会产生重复数据,这个问题该如何解决? - jmera
2个回答

107

如果您希望每个创建的实例重新评估值,则需要传递一个代码块。

与其

email   Faker::Internet.email

尝试...

email   { Faker::Internet.email }

11

使用Faker获取唯一性通过的属性可能是一种反模式。在测试中使用Faker的半随机输出也可能不是一个好主意-如果有时测试失败,你会因为Faker产生了你不期望的值而陷入一场疯狂的追逐游戏。

最近我一直在使用FactoryGirl的序列来获取可预测的、但仍然满足唯一性要求的值。

FactoryGirl.define do
  factory :user do
    sequence(:first_name, 1) { |n| "John#{n}" }
    sequence(:last_name, 1) { |n| "Doe#{n}" }
    sequence(:phone, 1) { |n| (111111111+n).to_s }               
    sequence(:email, 1) { |n| "email#{n}@example.com" }        
    password              "password"
    password_confirmation "password"
  end
end

FactoryGirl.create(:user).email #=> "email1@example.com"
FactoryGirl.create(:user).email #=> "email2@example.com"

这篇文章摘自Factory Girl技巧 @ http://arjanvandergaag.nl/blog/factory_girl_tips.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接