web-dev-qa-db-ja.com

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

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

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

85
Peter Nixey
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

偽物をブラケットで囲んでみてください。 このリンク を参照してください

154
Will Ayd

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

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

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

正しい答えを保存するために、ここではブログから転置されていますが、私は答えを信用しません。

以下のコードを使用すると、フェイカーは一意の名前を大量に生成しません

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

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

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

17
ocodo

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

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