Подтвердить что ты не робот

FactoryGirl + Faker - одинаковые данные генерируются для каждого объекта в данных семпла db

Я использую FactoryGirl и Faker для создания пользовательских объектов в моем файле seeds.rb, но по какой-то причине тот же самый пользователь создается и rake db:seed терпит неудачу из-за проверки уникальности электронной почты.

Factory для пользователей:

#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: Validation failed: Email has already been taken

Если я открою консоль и использую FactoryGirl.create(:user), я получаю те же результаты... один и тот же объект создается снова и снова, даже если я запускаю только Faker::Internet.email несколько раз, я получаю несколько сообщений электронной почты.

FactoryGirl:

[1] pry(main)> FactoryGirl.create(:user)
...
=> #<User id: 3, first_name: "Osvaldo", last_name: "Wunsch", email: "[email protected]", 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

Фейкер сам по себе:

[3] pry(main)> Faker::Internet.email
=> "[email protected]"
[4] pry(main)> Faker::Internet.email
=> "[email protected]"

Что мне здесь не хватает? Почему Faker производит одни и те же данные каждый раз при использовании через FactoryGirl?

4b9b3361

Ответ 1

Вам нужно передать блок, если вы хотите, чтобы значения были переоценены для каждого созданного экземпляра.

Вместо

email   Faker::Internet.email

попробовать...

email   { Faker::Internet.email }

Ответ 2

Использование 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 #=> "[email protected]"
FactoryGirl.create(:user).email #=> "[email protected]"

Взято из Factory Советы для девочек @http://arjanvandergaag.nl/blog/factory_girl_tips.html