factory_girlで使用すると、Fakerが重複データを生成します


86

Faker gemを使用して、いくつかの偽のデータをファクトリに入力しようとしています。

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

ただし、これにより、first_nameとlast_nameが異なるユーザーが生成されることを期待していますが、それぞれは同じです。

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

元の名前を再利用するだけでなく、Faker gemに各ユーザーの新しい名前を生成させるにはどうすればよいですか?


1
暗闇の中でのショットですが、次のようなものを使用してみましたuser.sequence(:first_name} {|n| Faker::Name::first_name}か?FactoryGirlは、「フィクスチャ」をロードするときに、Faker呼び出しを評価している可能性があります。sequence param,&blockメソッドを使用すると、それを防ぐことができます。
スティーブン

回答:


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

偽造者の周りにブラケットを配置してみてください。このリンクを参照してください


8
私はstackoverflowが大好きです-ありがとうウィル、あなたは私のベーコンを保存しました
Peter Nixey 2011年

ありがとう、これは私の問題を修正しました!
Oranges13 2012年

5
なぜ、なぜ、なぜ?ここで何が起こっているのですか?
jordanpg 2012

4
理由は「怠惰な属性」で、次を参照してください。github.com/thoughtbot/factory_girl/blob/master/...
Siweiシェン申思维

9
悲しいことに、これは常に機能するとは限りません。これは基本的に新しいランダムフェイカーオブジェクトを取得するだけですが、RNGのため、これが失敗する可能性があります。
Michael Lynch

45

利用可能な偽のデータの量が限られているため、Fakerはまだ重複データを提供している可能性があることに注意してください。

簡単なテストの目的と一意性の検証を行うために、私は以下を使用しました。

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

3
この答えはもっと賛成に値する。テストで多くのインスタンスが作成されると発生する可能性があります。
Enrico Carlesso 2015年

はい、エンリコに同意します。+1
karlingen 2015年

いい考えですが、姓と名を使用して電子メールを生成する場合、または形式を検証している場合(括弧:Pが付いている名前がわからない場合)、括弧を追加すると残りが壊れる可能性があります。
Cyril Duchon-Doris 2016

18

正解を保存するために、ここではブログから転座しています。私はその答えを信用しません。

以下のコードを使用する場合、偽造者は一意の名前を解き放ちません

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

ただし、中括弧を偽物の周りに配置すると、機能します。

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

理由を説明するために、最初の例は同じ名前を生成することです。一度だけ評価しています。2番目の例では、ファクトリが使用されるたびに評価します。

これは、{}遅延評価を提供するためです。基本的に、彼らはproc / lambdaにFaker呼び出しを戻り値として提供しています。


これを投稿していただきありがとうございます。Fakerがランダムなデータを生成できなかった理由がわかりませんでした。私が遭遇したすべての例は、私には奇妙に思えたシーケンスの使用方法を示しているようでした。Fakerを使用したかったので、各レコードはランダムであり、シーケンスされていません。Fakerの呼び出しを中かっこで囲むだけで問題は解決しました。シンプルでエレガント!
blimey85 2016年

5

属性に一意性の検証がある場合にシーケンスを使用する(効率が低い)代替方法は、提案された値がすでに存在するかどうかを確認し、一意になるまで新しい値を試し続けることです。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.