Faker produce dati duplicati quando viene utilizzato in factory_girl


86

Sto cercando di inserire alcuni dati falsi in una fabbrica utilizzando la gemma 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

Tuttavia, mentre mi aspetto che questo produca utenti con first_name e last_names diversi, ognuno è lo stesso:

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

Come posso fare in modo che la gemma Faker generi nuovi nomi per ogni utente e non solo riutilizzi quelli originali?


1
Solo uno scatto al buio, ma hai provato a usare qualcosa di simile user.sequence(:first_name} {|n| Faker::Name::first_name}? FactoryGirl sta probabilmente valutando la tua chiamata Faker quando carica i tuoi "proiettori". L'uso del sequence param,&blockmetodo dovrebbe impedirlo.
Steven

Risposte:


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

Prova a mettere parentesi intorno ai falsi. vedere questo collegamento


8
Adoro Stackoverflow così tanto - grazie Will, mi hai salvato la pancetta
Peter Nixey

Grazie, questo ha risolto il mio problema!
Arance13

5
Perché perché perché? Che cosa sta succedendo qui?
jordanpg

4
a causa di "attributo pigro", vedi: github.com/
thoughttbot/factory_girl/blob/master/…

9
Purtroppo questo non funziona sempre. Questo fondamentalmente ottiene solo un nuovo oggetto falso casuale, tuttavia a causa di RNG, c'è ancora una possibilità che fallisca.
Michael Lynch

45

Tieni presente che Faker potrebbe ancora fornire dati duplicati a causa della quantità limitata di dati falsi disponibili.

Per semplici scopi di test e per ottenere convalide di unicità, ho utilizzato quanto segue:

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

3
Questa risposta merita più voti positivi. È probabile che accada quando il tuo test crea molte istanze.
Enrico Carlesso

Sì, sono d'accordo con Enrico. +1
karlingen

Bella idea, ma l'aggiunta di parentesi può rompere il resto se usi nome e cognome per generare e-mail o hai convalide sul formato (non conosci nessun nome che ha parentesi: P).
Cyril Duchon-Doris

18

Per il bene di preservare la risposta corretta, qui è traslocata dal blog, non prendo alcun merito per la risposta.

Se usi il codice qui sotto, falsario non produrrà nomi univoci

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

Tuttavia, mettere le parentesi graffe intorno al falso fa funzionare!

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

Per spiegare perché, il primo esempio sta producendo gli stessi nomi. Valuta solo una volta. Il secondo esempio valuta ogni volta che viene utilizzata la fabbrica.

Ciò è dovuto alla {}valutazione pigra che fornisce. Essenzialmente stanno fornendo un proc / lambda con la chiamata Faker come valore di ritorno.


grazie per aver postato questo. Non riuscivo a capire perché Faker non fosse in grado di generare dati casuali e sembrava che ogni esempio che ho incontrato mostrasse come usare il sequenziamento che mi sembrava strano. Volevo usare Faker in modo che ogni record fosse casuale, non in sequenza. La semplice aggiunta di parentesi graffe attorno alle mie chiamate Faker ha risolto il problema. Semplice ed elegante!
Blimey85

5

Un'alternativa (meno efficiente) all'uso delle sequenze quando si dispone di una convalida di unicità su un attributo è controllare se un valore proposto esiste già e continuare a provarne di nuovi finché non è unico:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.