2010-05-30 1 views
40

has_many 'Bar'라는 모델 Foo이 있습니다. 나는이 객체들 각각에 대해 factory_girl 팩토리를 가지고있다. Bar의 공장에는 Foo와의 제휴가 있습니다. Bar가 생성되면 Foo를 인스턴스화합니다.factory_girl에서 자녀와 연관성 채우기

저는 Bar를 포함하고있는 Foo를 만드는 Factory를 원합니다. 이상적으로이 막대는 : bar 팩토리를 통해 만들어지며 Foo를 만드는 데 사용 된 빌드 전략 (작성/빌드)을 존중합니다.

바 팩토리를 호출 한 다음 새 바에서 Foo 참조를 가져올 수 있다는 것을 알고 있습니다. 나는 이것을 피하고 싶다. 내 테스트 케이스에서 중요한 객체는 Foo이다. Bar factory를 호출하는 것은 약간 순환적인 것으로 보입니다. 또한 여러 개의 막대가있는 Foo에 대한 필요성을 알 수 있습니다.

factory_girl에서 가능합니까? 이 관계를 부모에게 어떻게 정의합니까?

답변

48

Factory.after_ hooks이 성공적으로이 작업을 수행 할 수있는 유일한 방법이 될 것으로 보인다. 내가 코드를 복제하지 않고 빌드 전략을 유지하는 방법을 알아 냈어요 다음 :create 빌드 전략을 사용하는 경우 after_buildafter_create 전에 호출됩니다

Factory.define :foo do |f| 
    f.name "A Foo" 
    f.after(:build) { |foo| 
    foo.bars << Factory.build(:bar, :foo => foo) 
    } 
    f.after(:create) { |foo| 
    foo.bars.each { |bar| bar.save! } 
    } 
end 

documentation 상태. :build을 사용하면 after_build 만 호출되며 모두 만족합니다.

는 또한 건조하게 유지하기 위해 추상화 일반적으로-적용 버전 at this gist을 만들었습니다.

+2

완벽한 - 이것으로 내 머리카락을 찢어 버렸습니다. 감사! – recurser

+2

이것이 이것을하는 가장 좋은 방법이라고 생각하기는 어렵지만 여전히 그렇습니다. 이 답변에 대해 찬성표를 던졌습니다. – spier

+0

어떻게 요점 버전을 사용합니까? 이를 레일즈 애플리케이션에 통합하는 가장 좋은 방법은 무엇입니까? –

4

당신은 association 방법을 두 가지 방법을 사용할 수 있습니다

Factory.define :foo do |f| 
    # ... 
    f.association :bar 
end 

를 문제가 해결되지 않을 경우 수동 콜백을 사용하여 연결할 수 있습니다. 여기 내 애플 리케이션 중 하나의 예는 다음과 같습니다

Factory.define :live_raid do |raid| 
end 

Factory.define :live_raid_with_attendee, :parent => :live_raid do |raid| 
    raid.after_create { |r| Factory(:live_attendee, :live_raid => r) } 
end 
+1

첫 번째 구문 내 코드에서 스택 오버 플로우/무한 재귀가 발생에서 n 개의 자식 객체를 생성, factory_girl-4.5.0 사용. 두 번째 구문은 빌드 전략을 따르지 않는다는 점을 제외하고는 훌륭하게 작동합니다. –

3

FactoryGirl 지금 당신이 그것을 만드는 대신 연관된 객체를 구축 할 예정 협회에 사용할 수있는 :method => :build 옵션이 있습니다. i는 올바른 동작되는 것은 아니다 판단 부모 객체에 build 호출시

#64: Building an object creates associations

3

FactoryGirl 4.3.0 연관 save!에 호출된다.

FactoryGirl 코드를 파헤 치면 strategy: :build을 공장의 연관성 정의에 추가하면 save!을 호출하지 않고도 내 연관성을 생성 할 수 있습니다.

2

부모 객체 팩토리

FactoryGirl.define do 
    factory :foo do 
    name "test"   

    after(:build) do |instance| 
     n.times { instance.bars << FactoryGirl.create(:bar) }   
    end 
    end 
end