2012-06-01 6 views
10

私はFactoryGirlを初めて使用しており、次のような単純なシナリオを試していますか?そして、私のテストでファクトリーガールは既存のオブジェクトとの関連付けを作成します

factory :female, :class => Gender do 
    code 'Female' 
end 

factory :male, :class => Gender do 
    code 'Male' 
end 

factory :papas, :class => Customer do 
    first_name 'Jim' 
    last_name 'Papas' 
    association :gender, :factory => :male, :strategy => :build 
end 

factory :dumas, :class => Customer do 
    first_name 'Mary' 
    last_name 'Dumas' 
    association :gender, :factory => :female, :strategy => :build 
end 

:Customerクラスがassocation belongs_toGenderクラスとgender_idが存在しなければならないと述べている検証ルールを持っていることを

create(:male) 
create(:female) 
create(:papas) 
create(:dumas) 

注意。私はコード上で一意性のためのGenderクラスのバリデーションを持っています。

上記の文create(:papas)gender_idnilあるので、私のテストでは、私は、作成されようとしているCustomerが有効でないというエラーが発生します。

私は性別と:strategy => :build:papasCustomerの工場の関連付けを削除すると、私は:papasを作成しようとすると、性別のコードがすでに存在していること、エラーが発生します。

私のテストでは上記の必要なデータを作成するために何が必要なのですか?

他のテストでも、顧客なしで作成された性別を作成したいと考えています。ファクトリ作成コマンドで顧客を作成し、同時に顧客が性別を作成できるようにしてはいけません。同じ性別の2人の顧客を作成しようとすると、これは機能しません。

また、1より良い答えが存在しなければならない:

@male = create(:male) 
@female = create(:female) 
create(:papas, :gender => @male) 
create(:dumas, :gender => @female) 

(備品を使用する場合はこれらの事はすぐに準備ができていた私は、器具に戻りましょう。?)

答えて

14

Genderインスタンス用のファクトリを使用せず、Customerファクトリでコールバックを使用することで、必要なものを実現できます。

あなたはGenderファクトリーからそれほど多くの利益を得ることはできません(私はこの質問をするために簡素化されていると思うが)。あなたは同じように簡単に性別を取得するためにこれを行うことができます:

Gender.find_or_create_by_code!('Male') 

次にあなたが性別を設定するために、コールバックの前に使用することができ、あなたの顧客の工場で:

factory :dumas, :class => Customer do 
    first_name 'Mary' 
    last_name 'Dumas' 
    before_create do |customer| 
    customer.gender = Gender.find_or_create_by_code!('Female') 
    end 
end 

形式をfactory_girlでコールバックを使用するためにしています最近、あなたは3.3以降を使用している場合あなたがする必要がありますので、変更:

before(:create) do |customer| 

の代わりbefore_create

性別を作成するのがあなたの例よりも複雑な場合でも、ファクトリを使用して性別を作成できますが、find_by_code!インスタンスとfind_or_create_by_code!を使用してコールバックを使用して顧客と結びつけます。

+0

備品対非常に冗長、あなたの答えが正しいですが。私は最後の2ヶ月の工場の女の子を使っていて、まだ次のプロジェクトには備品があります! –

+1

多くの異なる顧客を作成する必要がある場合は、工場で見つけることができます。あなたはmale_customerファクトリーとfemale_customerファクトリーを持ち、それらを異なる顧客の親ファクトリーとして使用することができます。これにより、冗長性が大幅に削減されます。それはうまくいってうれしい! – Shadwell

5

ignoreブロックは、同様にこれをラップするために使用することができます。

factory :dumas, :class => Customer do 
    ignore do 
    female { Gender.find_by_code('Female') || create(:female) } 
    end 

    first_name 'Mary' 
    last_name 'Dumas' 
    gender { female } 
end 
5

ignoreは廃止され、ファクトリー・ガールのバージョン5に削除されます。

代わりに、あなたはtransient attributesを使用することができます。

factory :dumas, :class => Customer do 
    transient do 
    female { Gender.find_by_code('Female') || create(:female) } 
    end 

    first_name 'Mary' 
    last_name 'Dumas' 
    gender { female } 
end 
関連する問題