2013-04-14 4 views
10

Hier ist ein Beispiel aus dem factory documentation:factory Attribut definieren, indem Methode auf einem anderen Werk Aufruf

FactoryGirl.define do 
    factory :post do 
    name "Post name" 
    user 
    end 
end 

In diesem Beispiel user eine weitere Fabrik aufruft. Was ich tun möchte, ist effektiv user.id aufrufen, aber es als die Definition eines Attributs festlegen. Hier ist ein abgespeckte Beispiel:

**models/job.rb** 
    ... 
    belongs_to :assignee, :class_name => "User" 
    belongs_to :user 
    ... 
    attr_accessible :assignee_id, :user_id 
    ... 
end 


**factories/jobs.rb** 
FactoryGirl.define do 
    factory :job do 
    assignee_id user.id  #what I would like to do, but triggers "undefined method 'id'" error 
    user_id user.id   #user_id is an attribute of the model and is the job assignor 
end 

Ich habe versucht, den Teil der Dokumentation zu integrieren, die Aliase diskutiert, aber ohne Glück:

FactoryGirl.define do 
    factory :user, :aliases => [:assignee] do 
    .... 

Ich fühle mich wie ich (Hoffnung?) m hier schließen, aber jede Einsicht wird geschätzt. Vielen Dank.

EDIT: Dieser Code ruft meine Spezifikationen auf!

**factories/jobs.rb** 

FactoryGirl.define do 
    factory :job do 
    before(:create) do |job| 
     user = FactoryGirl.create(:user) 
     job.assignee = user 
     job.user = user 
    end 

    association :assignee, factory: :user 
    association :user, factory: :user 
    sequence(:user_id) { |n| n } 
    sequence(:assignee_id) { |n| n } 
    ... 
end 

Und es geht meine it { should be_valid } spec, so scheint es, dass die Fabrik in Ordnung, obwohl ich glaube, ich habe einige Refactoring in der Spezifikation selbst wenn ich FactoryGirl.create nenne.

Der obige Code enthält die Vorschläge von mguymon. Vielen Dank!

FINAL UPDATE

Nachdem er wieder und wieder zu lesen Hartl's discussion on model associations, ich war in der Lage, diese Frage zu stellen, um auszuruhen. Was ich oben hatte, war technisch gültig, aber übergab die Attribute nicht richtig, wenn ich Jobs in meiner Spezifikation erstellte oder erstellte. Hier ist, was ich hätte haben sollen:

FactoryGirl.define do 
    factory :job do 
    association :assignee, factory: :user 
    user 
    end 
end 

Mein Problem ergab sich auch aus, wie ich Fabriken in meinem spec zu schaffen, so ist hier, wie ich es getan haben sollte (aber nicht ... seufz):

let(:user) { create(:user) } 
    before { @job = create(:job, user: @user) } 

Es scheint, dass ich nicht explizit association :user in meiner Fabrik haben muss, noch brauche ich den before Block von oben.

Als beiseite, ich habe auch gelernt, dass ich, indem puts @job innerhalb einer expect Anweisung debuggen können, oder @job.assignee_id sicherstellen rufen, dass die Attribute ordnungsgemäß geladen werden. Wenn diese bestimmte Spezifikation ausgeführt wird, wird die puts Anweisung direkt von der Spezifikation F oder . ausgegeben.

+0

Sorry, aber können Sie die Ausnahme Stack Trace anzeigen? danke – ted

Antwort

14

Für die neueste Version von factory verwenden association anderen Active Modelle zur Karte:

factory :job do 
    # ... 
    association :assignee, factory: :user 
end 

Diese gerade aus the docs ist.


Aus dem Fehler, den Sie geschrieben, es ist unter Angabe Sie die user.id zu bekommen versuchen, aber user ist keine Active Instanz, sondern ein Proxy von factory. Sie erhalten diesen Fehler nicht, wenn Sie die Methode association verwenden. Wenn Sie direkt auf ein Modell zugreifen müssen, müssen Sie es zuerst manuell erstellen.Sie können dies tun, um einen Block in Ihrem Werk, indem:

factory :job do 
    assignee_id { FactoryGirl.create(:user).id } 
end 

Es sieht aus wie Sie das gleiche Modell versuchen zweimal zu assoziieren, das für Sie before_create Rückruf verwenden können, ein User-Modell zu erstellen und zuweisen, um user und :

factory :job do 

    before(:create) do |job| 
     user = FactoryGirl.create(:user) 
     job.assignee = user 
     job.user = user 
    end 
end 
+0

Danke für die Antwort und den Link. Selbst mit der Assoziation (die ich sicher brauche) bekomme ich immer noch einen "undefined method 'id'" -Fehler. – aceofbassgreg

+0

Ihr Schnitt hat den Trick gemacht. Nun, da meine Spezifikationen endlich ausgeführt werden, muss ich einige problematische Fehler beheben, die durch doppelte Benutzer verursacht wurden ... – aceofbassgreg

+0

Es stellt sich heraus, dass ich weder 'vorher' (: create) benötigt habe, noch musste ich einen Benutzer aus dem erstellen Fabrik. Obwohl meine Factory als gültig getestet wurde, wurden die Attribute nicht ordnungsgemäß in die Jobs geladen, die ich in meinen Spezifikationen erstellt oder erstellt habe (dies wurde durch die Verwendung von puts @job in den Spezifikationen überprüft). Ich habe den richtigen Code (oder zumindest eine bessere Version ... vielleicht gibt es eine "korrekere" Version) zu meiner Frage hinzugefügt, aber ich lasse Ihre Antwort als die überprüfte Antwort, da ich explizit die Verknüpfung zuordnen musste Bevollmächtigter mit dem Benutzer und würde das ohne Ihre Hilfe nicht bekommen. – aceofbassgreg