2

Ich habe zwei voneinander abhängige Modelle, Konto und Benutzer. Ein Konto wird immer von einem Benutzer erstellt, dessen ID somit im creator_id-Attribut des Kontos gespeichert ist, und ein Benutzer gehört notwendigerweise zu einem Konto (die Anzahl der zu einem Konto gehörenden Benutzer ist jedoch unbegrenzt). Diese Informationen werden im Benutzer gespeichert Attribut account_id Derselbe Benutzer kann verschiedene Konten erstellt haben.Wie Laden Fixtures in einer bestimmten Reihenfolge in Rails 5

Ich drückte auf diese Weise diese Regeln:

User-Modell:

belongs_to :account, inverse_of: :users 
has_many :created_accounts, class_name: "Account", :foreign_key => "creator_id" 

Konto Modell:

belongs_to :creator, class_name: 'User', optional: true 
has_many :users, inverse_of: :account 

Als sie voneinander abhängig sind, habe ich eine schmutzige Abhilfe verwendet der Lage sein, zu instanziiert sie: Ich erstelle zuerst das Konto, und nach dieser Aktion erzwinge ich den Benutzer, ihr Profil zu erstellen, und ihre Benutzer-ID wird dem Konto als Creator_id in einem Update hinzugefügt.

Deshalb habe ich im Account-Modell:

validate :require_actual_creator_id, on: :update 
------------------------------------------------ 
def require_actual_creator_id 
    User.find(creator_id) 
    end 

Ich war auf einem Authentifizierungssystem arbeitet nur das Benutzermodell beteiligt, also musste ich diese Zeilen bis gestern kommentiert, wenn ich sie unkommentiert.

Ich lief db: migrate: reset, db: seed und db: migrieren RAILS_ENV = Test ohne Probleme, beide Modelle haben ein normales Verhalten in der Konsole, aber wenn es um Fixtures geht (zB testing oder db: fixtures: Last), ich folgende Fehlermeldung bekam:

NoMethodError: undefined method `id' for nil:NilClass 
/home/vincent/workspace/bam-rails/test/fixtures/users.yml:16:in `get_binding' 

Hier ist eine typische Leuchte das Problem verursacht, die Linie 16 die eine kommentierte werden:

michael: 
    id: 1 
    handle: Michael Example 
    email: [email protected] 
    encrypted_password: <%= User.generate_encrypted_token('password') %> 
    role_id: <%= User::ADMIN %> 
    is_activated: true 
    activated_at: <%= DateTime.now %> 
    #account_id: <%#= Account.first.id %> 

Wenn ich diese letzte Zeile Kommentar, es gibt kein Problem nicht mehr. Allerdings möchte ich passende Fixtures für meine Tests laden, weil zum Beispiel der hier erstellte Benutzer nicht gültig ist.

Ich lese in this post, dass die Leuchten in alphabetischer Reihenfolge geladen werden. Wenn das richtig ist, kann ich nicht verstehen, warum ich diese Zeile kommentieren muss, weil Accounts vor den Benutzern geladen werden sollen.

Ich fand that solution zu arbeiten, aber es ist nicht aus der offiziellen Dokumentation und es ist ziemlich alt, aus dem Jahr 2007 datiert. Ich fürchte, das würde aufhören, von einem Tag auf den nächsten zu arbeiten.

Kann jemand die Geräte in einer benutzerdefinierten Reihenfolge in Rails 5 richtig laden, oder hat eine andere Lösung für mein Problem? Vielen Dank im Voraus.

Antwort

2

Das Problem, das Sie haben, hängt vollständig davon ab, wie Sie Ihren Code organisiert haben. In der Umgebung, in der Sie das erste Konto erstellen, treten Probleme auf. Die Tatsache, dass Ihr Benutzer zu dem Zeitpunkt, zu dem er instanziiert wurde, nicht zuerst existiert, weil die Geräte noch nicht geladen sind; davon sind Sie sicher überzeugt. Fixtures sind notorisch spröde, deshalb entfernen sich Leute oft von ihnen, je komplexer ihr Code wird. In diesem Fall, obwohl Sie helfen, einen Code Geruch zu entlarven, jedes Mal, wenn die Bestellung oder Ausführung Sie testen oder grundlegende nicht testfallspezifische Einrichtung verursacht Probleme, die Sie haben ein Problem mit Ihrem Code. Ich schlage vor, dass Sie einen Weg finden, diese "schmutzige Arbeit" zu benutzen.

Nun, wenn Sie aus irgendeinem Grund verheiratet sind mit der Art und Weise, wie Ihr Code derzeit organisiert ist, schlage ich vielleicht Wechsel zu factory girl, gibt es Ihnen ein wenig mehr Flexibilität, um den Punkt zu steuern, an dem Ihre Mock-Objekte instanziiert werden Sie nicht laufe auf dieses Problem ein. Ich werde jedoch sagen, dass dies Ihnen nur ermöglichen wird, Sie auf diesem Weg weiter zu führen, der mehr als wahrscheinlich nur zu weiteren Problemen auf der Straße führen wird, Ihre beste Wette ist es, die Funktion neu zu implementieren.

+0

Vielen Dank für Ihre Antwort. Factor Mädchen scheint praktisch, ich kann es in Zukunft verwenden. Wie mein Code organisiert ist, kann ich leider nicht ändern, weil ich nicht derjenige bin, der sich dafür entscheidet. Allerdings fand ich die Lösung für mein präzises Problem, das nicht darin bestand, die ID mit erb und User.first.id zu erzeugen, sondern einfach in Klartext, wie '1' zu schreiben. Auf diese Weise können Sie nicht sicher sein, dass es sich um eine tatsächliche ID handelt und das Objekt möglicherweise ungültig ist, aber zumindest gibt es eine ID, und wenn Sie Ihre Fixtures sorgfältig verwalten, entspricht dies einem tatsächlichen Datensatz. –

+0

Nur warn ich benutze, um auf einer Code-Basis zu arbeiten, die auf bestimmten Datensätzen in der Datenbank beruhte, führte dies buchstäblich zu Albträumen. Sie möchten, dass Ihr Code so zustandslos wie möglich ist, aber ich bin froh, dass Sie aus dem Schlamm sind. –

Verwandte Themen