2013-01-21 9 views
28

einrichten Ich habe mit der Einrichtung einer has_many/through Beziehung mit Factory Girl kämpfen.Factory Girl: Wie man eine has_many/durch die Verbindung

Ich habe folgende Modelle:

class Job < ActiveRecord::Base 
    has_many :job_details, :dependent => :destroy 
    has_many :details, :through => :job_details 
end 

class Detail < ActiveRecord::Base 
    has_many :job_details, :dependent => :destroy 
    has_many :jobs, :through => :job_details 
end 

class JobDetail < ActiveRecord::Base 
    attr_accessible :job_id, :detail_id 
    belongs_to :job 
    belongs_to :detail 
end 

Meine Factory:

factory :job do 
    association  :tenant 
    title   { Faker::Company.catch_phrase } 
    company   { Faker::Company.name } 
    company_url  { Faker::Internet.domain_name } 
    purchaser_email { Faker::Internet.email } 
    description  { Faker::Lorem.paragraphs(3) } 
    how_to_apply { Faker::Lorem.sentence } 
    location  "New York, NY" 
end 

factory :detail do 
    association :detail_type <--another Factory not show here 
    description "Full Time" 
end 

factory :job_detail do 
    association :job 
    association :detail 
end 

Was ich will, ist für meine Arbeit Werk mit einem Standard Detail von "Vollzeit" geschaffen werden.

Ich habe versucht, dies zu folgen, haben aber kein Glück gehabt: FactoryGirl Has Many through

Ich bin nicht sicher, wie die after_create verwendet werden sollte, die Details über JobDetail zu befestigen.

Antwort

30

Versuchen Sie etwas wie das. Sie möchten ein detail-Objekt erstellen und es an die Detailzuordnung des Jobs anfügen. Wenn Sie after_create verwenden, wird der erstellte Auftrag an den Block zurückgegeben. So können Sie FactoryGirl verwenden, um ein Detailobjekt zu erstellen und es den Details des Jobs direkt hinzuzufügen.

factory :job do 
    ... 

    after_create do |job| 
    job.details << FactoryGirl.create(:detail) 
    end 
end 
+0

Das hat super funktioniert, danke. Eine Frage - das Hinzufügen von after_create funktioniert, aber es antwortet mit 'DEPRECATION WARNING: Sie versuchen, ein Attribut' detail_id 'zu erstellen. Das Schreiben beliebiger Attribute in einem Modell ist veraltet. Bitte benutze 'attr_writer' etc. nur irgendwelche Ideen? – cman77

+11

Ich weiß, das ist alt, aber in FactoryGirl verwenden Sie jetzt Callbacks mit dem Format 'after (: create)' 'anstelle von' after_create'. Der Rest der Antwort sollte immer noch ohne Fehler funktionieren. – Arel

+0

mehr Infos auf 'nach (: erstellen)' Callbacks: http://robots.thoughtbot.com/get-your-callbacks-on-with-factory-girl-3-3 – Brian

2

Dieser arbeitete für mich

FactoryGirl.define do 
    factory :job do 

    # ... Do whatever with the job attributes here 

    factory :job_with_detail do 

     # In later (as of this writing, unreleased) versions of FactoryGirl 
     # you will need to use `transitive` instead of `ignore` here 
     ignore do 
     detail { create :detail } 
     end 

     after :create do |job, evaluator| 
     job.details << evaluator.detail 
     job.save 
     job_detail = job.job_details.where(detail:evaluator.detail).first 

     # ... do anything with the JobDetail here 

     job_detail.save 
     end 
    end 
    end 
end 

Dann später

# A Detail object is created automatically and associated with the new Job. 
FactoryGirl.create :job_with_detail 

# To supply a detail object to be associated with the new Job. 
FactoryGirl.create :job_with_detail detail:@detail 
+0

Ich weiß, dass das alt ist, aber ich bin neugierig, was das besser macht als die akzeptierte Antwort hier? – rorykoehler

+0

Als ich die ursprüngliche Antwort gelesen habe, gab es im Beispiel nicht genug Informationen für meinen Geschmack. Dies fügt zusätzliche Funktionen zusätzlich zu dieser Antwort hinzu, da Sie 'create: job_with_detail' mit oder ohne die Option' detail: @detail' verwenden können. Wenn nicht, wird das Detail automatisch erstellt. – Nate

4

ich dieses Problem heute konfrontiert und ich eine Lösung gefunden. Hoffe, das hilft jemandem.

FactoryGirl.define do 
    factory :job do 

    transient do 
     details_count 5 # if details count is not given while creating job, 5 is taken as default count 
    end 

    factory :job_with_details do 
     after(:create) do |job, evaluator| 
     (0...evaluator.details_count).each do |i| 
      job.details << FactoryGirl.create(:detail) 
     end 
     end 
    end 
    end 
end 

Dies ermöglicht einen Job wie diesen

create(:job_with_details) #job created with 5 detail objects 
create(:job_with_details, details_count: 3) # job created with 3 detail objects 
+0

funktioniert gut mit dem neuesten alles ab sofort (Schienen 5, rspec 3.5, Factorygirl 4.8) – jpwynn

0

Sie dieses Problem lösen können auf folgende Weise zu erstellen:

FactoryBot.define do 
    factory :job do 
    # job attributes 

    factory :job_with_details do 
     transient do 
     details_count 10 # default number 
     end 

     after(:create) do |job, evaluator| 
     create_list(:details, evaluator.details_count, job: job) 
     end 
    end 
    end 
end 

Mit diesem können Sie ein job_with_details erstellen, das hat Optionen, um anzugeben, wie viele Details gewünscht werden. Sie können this interesting article für weitere Details lesen.