Faker erzeugt doppelte Daten, wenn es in factory_girl verwendet wird

85

Ich versuche, einige gefälschte Daten mit dem Edelstein Faker in eine Fabrik zu füllen:

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

Obwohl ich davon ausgehe, dass dies Benutzer mit unterschiedlichen Vor- und Nachnamen hervorbringt, ist jeder gleich:

>> Factory(:user)
=> #<User id: 16, email: "[email protected]", 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: "[email protected]", created_at: "2011-03-18 18:29:39", 
updated_at: "2011-03-18 18:29:39", first_name: "Bailey", last_name: "Durgan">

Wie kann ich das Faker-Juwel dazu bringen, neue Namen für jeden Benutzer zu generieren und nicht nur die ursprünglichen wiederzuverwenden?

Peter Nixey
quelle
1
Nur ein Schuss in die Dunkelheit, aber haben Sie versucht, so etwas zu verwenden user.sequence(:first_name} {|n| Faker::Name::first_name}? FactoryGirl wertet wahrscheinlich nur Ihren Faker-Aufruf aus, wenn es Ihre "Fixtures" lädt. Die Verwendung der sequence param,&blockMethode sollte dies verhindern.
Steven

Antworten:

156
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

Versuchen Sie, die Fälscher in Klammern zu setzen. siehe diesen Link

Will Ayd
quelle
8
Ich liebe Stackoverflow so sehr - danke Will, du hast meinen Speck gerettet
Peter Nixey
Vielen Dank, dies hat mein Problem behoben!
Orangen13
5
Warum, warum, warum? Was geht hier vor sich?
Jordanpg
4
Wegen "fauler Attribute", siehe: github.com/thoughtbot/factory_girl/blob/master/…
Siwei Shen 21
9
Leider funktioniert das nicht immer. Dies führt im Grunde nur zu einem neuen zufälligen Fälscherobjekt. Aufgrund von RNG besteht jedoch immer noch die Möglichkeit, dass dies fehlschlägt.
Michael Lynch
45

Beachten Sie, dass Faker aufgrund der begrenzten Menge an verfügbaren gefälschten Daten möglicherweise immer noch doppelte Daten bereitstellt.

Für einfache Testzwecke und zur Überprüfung der Eindeutigkeit habe ich Folgendes verwendet:

sequence(:first_name) {|n| Faker::Name::first_name + " (#{n})"}
sequence(:last_name) {|n| Faker::Name::last_name + " (#{n})"}
ZweimalB
quelle
3
Diese Antwort verdient mehr positive Stimmen. Es ist wahrscheinlich, dass Ihr Test viele Instanzen erstellt.
Enrico Carlesso
Ja, ich stimme Enrico zu. +1
Karlingen
Gute Idee, aber das Hinzufügen von Klammern kann den Rest beschädigen, wenn Sie zum Generieren von E-Mails Vor- und Nachnamen verwenden oder das Format validiert haben (Sie kennen keinen Namen mit Klammern: P).
Cyril Duchon-Doris
18

Um die richtige Antwort zu erhalten, wird sie hier aus dem Blog übersetzt. Ich nehme die Antwort nicht zur Kenntnis.

Wenn Sie den folgenden Code verwenden, gibt faker keine eindeutigen Namen aus

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

Wenn Sie jedoch geschweifte Klammern um den Fälscher legen, funktioniert dies!

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

Um zu erklären, warum, produziert das erste Beispiel die gleichen Namen. Es wird nur einmal ausgewertet. Das zweite Beispiel wird jedes Mal ausgewertet, wenn die Fabrik verwendet wird.

Dies ist auf die {}träge Bewertung zurückzuführen. Im Wesentlichen stellen sie ein proc / lambda mit dem Faker-Aufruf als Rückgabewert bereit.

ocodo
quelle
Vielen Dank für die Veröffentlichung. Ich konnte nicht herausfinden, warum Faker keine zufälligen Daten generieren konnte, und es schien, als ob jedes Beispiel, auf das ich stieß, zeigte, wie man Sequenzierung verwendet, was mir seltsam erschien. Ich wollte Faker verwenden, damit jeder Datensatz zufällig und nicht sequenziert ist. Das Hinzufügen von Klammern um meine Faker-Anrufe löste das Problem. Einfach und elegant!
Blimey85
5

Eine (weniger effiziente) Alternative zur Verwendung von Sequenzen, wenn Sie eine Eindeutigkeitsüberprüfung für ein Attribut haben, besteht darin, zu überprüfen, ob ein vorgeschlagener Wert bereits vorhanden ist, und neue zu versuchen, bis er eindeutig ist:

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
Dan Kohn
quelle