web-dev-qa-db-ja.com

Factory Girlでファクトリの複数のインスタンスを作成/ビルドする方法は?

同じクラスの複数のレコードまたは複数のファクトリを作成するにはどうすればよいですか?

私は試した:

Factory.define :user do |user|
  user.email "[email protected]"
  user.password "somepassword"

  user.email "[email protected]"
  user.password "somepassword"
end

そして

Factory.define :user do |user|
  user.email "[email protected]"
  user.password "somepassword"
end

Factory.define :user do |user|
  user.email "[email protected]"
  user.password "somepassword"
end

しかし、それは機能しません--Attribute already defined: email

26
benoitr

ファクトリを使用するには2つのステップがあります。1つはファクトリを定義すること、もう1つはファクトリを使用することです。

1)それらを定義する:

Factory.define :user do |u|
  u.sequence(:email) { |n| "mike#{n}@awesome.com"}
  u.password "password123"
end

2)それらの使用:

例として、仕様でそれらを使用する場合があります。

 @user1 = Factory(:user) #has an email of [email protected]
 @user2 = Factory(:user) # has an email of [email protected] due to sequences in FG

私はこれを見ます Railscast それをより良く感じるために。

23
Mike Lewis

これは古い質問と回答ですが、Googleで最初に見つけた結果だったので、Building orCreatingという見出しの下に docs から以下を追加すると思いました。複数のレコード

created_users = FactoryGirl.create_list(:user, 25)  #creates 25 users

twenty_year_olds = FactoryGirl.build_list(:user, 25, date_of_birth: 20.years.ago)  #builds 25 users, sets their date_of_birth

これをRailsコンソールで実行する場合は、ここで次の回答を検討してください: https://stackoverflow.com/a/23580836/4880924

先ほど引用した例では、ファクトリ定義でsequenceが使用されている場合、各ユーザーは異なるユーザー名を持ちます(上記のMike Lewisの回答を参照)。

43
aceofbassgreg

同じ(ベース)ファクトリからのレコードに異なる値を持たせたい場合は、いくつかのオプションがあります。

A)定義された属性を上書きする

factory :post, aliases: [:approved_post] do
  title "A title"
  approved true
end

approved_post = create(:approved_post)
unapproved_post = create(:post, approved: false)

B)継承

factory :post do
  title "A title"

  factory :approved_post do
    approved true
  end

  factory :unapproved_post do
    approved false
  end
end

approved_post = create(:approved_post)
unapproved_post = create(:unapproved_post)

C)シーケンス

factory :user do
  sequence(:email, 1000) { |n| "person#{n}@example.com" }
end

D)特性

factory :post do
  title "My awesome title"

  trait(:approved) { approved true }

  trait(:unapproved) { approved false }

  trait :with_comments do
    after(:create) do |instance|
      create_list :comment, 2, post: instance
    end
  end

  factory :approved_post_with_comments, traits: [:approved, :with_comments]
end

approved_post_with_comments = create(:approved_post_with_comments)
unapproved_post_with_no_comments = create(:post, :unapproved, title: "Test")
post_with_title = build(:post)

これらの方法は組み合わせることができます。この例では、リストとペアをシーケンスとオーバーライドで使用します。

factory :user do
  sequence(:username) { |n| "user#{n}" }
  date_of_birth Date.today
end

# Build a pair and a list of users.
two_newborns     = build_pair(:user)
ten_young_adults = build_list(:user, 10, date_of_birth: 20.years.ago)

# Create a pair and a list of users.
two_young_adults = create_pair(:user, date_of_birth: 20.years.ago)
ten_newborns     = create_list(:user, 10)

私は可能な限り特性を使用することを好みます、私はそれらが柔軟であると思います。

32
Dennis

現在の_factory_girl_Rails_ 4.6.0では、build(:model)が常にオブジェクトの同じインスタンスを返すという何らかの関連する問題がありました。 sequence(:name) ...を使用しても、それは修正されませんでした。だから私はこのようないくつかの偽の(空の)特性を生成しました:

_FactoryGirl.define do
  factory :model do
     ...
     # fake traits to urge factory_girl to always return a new instance:
    (1..5).each {|n| trait "var#{n}".to_sym }
  end
end
_

そして、build(:model, :var1), build(:model, :var2)...を呼び出します

0
TNT