85 votes

Faker produit des données en double lorsqu'il est utilisé dans factory_girl

J'essaie d'introduire de fausses données dans une usine en utilisant la gemme Faker :

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

Cependant, bien que je m'attende à ce que cela produise des utilisateurs ayant des noms et des prénoms différents, chacun d'entre eux est le même :

>> 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">

Comment puis-je faire en sorte que la gemme Faker génère de nouveaux noms pour chaque utilisateur et ne se contente pas de réutiliser les noms originaux ?

154voto

Will Ayd Points 2832
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

Essaie de mettre des parenthèses autour des faux. Regarde. ce lien

44voto

TwiceB Points 21

Notez que Faker peut encore fournir des données en double en raison de la quantité limitée de fausses données disponibles.

Pour des tests simples et pour passer les validations d'unicité, j'ai utilisé ce qui suit :

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

18voto

EmacsFodder Points 12284

Afin de préserver la bonne réponse, la voici transposée du blog, je ne m'attribue aucun mérite pour la réponse.

Si vous utilisez le code ci-dessous, faker ne produira pas de noms uniques.

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

Cependant, en mettant des accolades autour de faker, cela fonctionne !

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

Pour expliquer pourquoi, le premier exemple produit les mêmes noms. Il ne l'évalue qu'une fois. Le second exemple est évalué à chaque fois que la fabrique est utilisée.

Cela est dû à la {} fournir une évaluation paresseuse. Essentiellement, ils fournissent une proc/lambda avec l'appel Faker comme valeur de retour.

5voto

dankohn Points 6999

Une alternative (moins efficace) à l'utilisation de séquences lorsque vous avez une validation d'unicité sur un attribut est de vérifier si une valeur proposée existe déjà et de continuer à en essayer de nouvelles jusqu'à ce qu'elle soit 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X