5

Ich habe ein Juwel geschrieben, das Google Spreadsheets in Rails-Modelle umgewandelt werden kann. Die Abfolge dieses Prozesses beinhaltet das Erstellen aller Modelle, anschließendes Verknüpfen ihrer Assoziationen und das Speichern aller Modelle. Es unterstützt alle Arten von Assoziationen, die verfügbar sind, und in jedem Fall wird der erste Balken erstellt, indem die Modelle erstellt, Assoziationen hergestellt und dann die Modelle korrekt gespeichert werden. Die Ausnahme ist, wie folgt:Etablierung eines Has One Through vs hat viele mit nicht gespeicherten Models

Ich habe eine einfache has_one, through Assoziation (Zugang der Kürze halber weggelassen Attribut):

class Left < ActiveRecord::Base 
    has_many :middles, dependent: :destroy 
    has_many :rights, through: :middles 
end 

class Right < ActiveRecord::Base 
    has_one :middle, dependent: :destroy 
    has_one :left, through: :middle 
end 

class Middle < ActiveRecord::Base 
    belongs_to :left 
    belongs_to :right 
end 

Ich bin etwas inkonsistentes Verhalten zu finden, je nachdem, welche Seite die Zuordnung des Vereins besteht:

left = Left.new 
right = Right.new 
left.rights << right 
left.middles #[] 
right.middle #nil 
left.save! 
left.middles # <Middle theme_id: 1, archive_resource_id: 1 > 

rechts Zuordnung nach links::

rechts Zuordnung nach links

left = Left.new 
right = Right.new 
right.left = left 
left.middles #[] 
right.middle <Middle theme_id: nil, archive_resource_id: nil > 
right.save! 
right.middle # <Middle theme_id: nil, archive_resource_id: 1 > 

Dieses Verhalten scheint sehr inkonsistent. Warum ist das? Warum funktioniert das in die eine Richtung und nicht in die andere? Gibt es eine Möglichkeit, diese Beziehung mit beiden ungesicherten Aufzeichnungen herzustellen?

Ich schätze, dass die offensichtliche Lösung ist alles zu retten, bevor die Beziehungen einrichten, aber wie oben erläutert, muss ich die Modelle nicht gespeicherten sein, wenn die Verbände etabliert, und in jeder anderen Art von Vereinigung gibt ist in dieser Hinsicht kein Problem.

+0

Wenn '' 'Left''' und' '' Right''' Modelle auch geerbt von '' 'Activerecord :: Base '' '? Auch warum '' 'Left''' Modell' '' has_many: right'''? Vielleicht sollte es '' 'has_many: rightS''' oder' '' has_one: right''' sein? – freemanoid

+0

@freemanoid Sorry, ja sie sind (geändert in Frage). – Undistraction

+2

'' 'has_many: middleS''' und' '' has_many: rightS''' – freemanoid

Antwort

-1

Ich denke, es funktioniert wahrscheinlich, aber nicht sofort aktualisiert. Versuchen Sie, true zu übergeben, wenn Sie Ihre Verknüpfungsmethoden aufrufen. Ex. right.middle(true). Dies zwingt Rails, zurück zur Datenbank zu gehen, um den Datensatz zu erhalten, anstatt den Cache zu überprüfen, was veraltet ist. Tun Sie dies jedoch nicht bei neuen Aufnahmen, da Sie das zugehörige Objekt im Speicher wegblasen.

Um zu vermeiden, einen Reload zu erzwingen, setzen inverse_of auf Ihrer Verbände:

class Left < ActiveRecord::Base 
    has_many :middles, dependent: :destroy, inverse_of: :left 
    has_many :rights, through: :middles 
end 

class Right < ActiveRecord::Base 
    has_one :middle, dependent: :destroy, inverse_of: :right 
    has_one :left, through: :middle 
end 

class Middle < ActiveRecord::Base 
    belongs_to :left, inverse_of: :middles 
    belongs_to :right, inverse_of: :middle 
end 

inverse_of eine Beziehung model bewusst eines zugehörigen Modells macht sich, die es „smart“ zu persistierenden und Laden sein können zugehörige Objekte.

+0

Leider wird 'inverse_of' für' through' Assoziationen nicht unterstützt: Siehe: http://stackoverflow.com/questions/7436173/activerecord-inverse-of-does-not-work-on-has-many-through- on-the-join-model-on – Undistraction

+0

Ähm, ja. Es tut uns leid. Es war spät. – Kaleidoscope

+0

Kein Problem. Abstimmen, so ist es klar, diese Antwort ist falsch. – Undistraction

0

Wie pro die Rails API-Dokumentation (link) -

Wenn Sie eine belongs_to auf dem Modell verbinden, ist es eine gute Idee, setzen die: inverse_of Option auf der belongs_to, was bedeuten wird dass die folgende Beispiel funktioniert richtig (wo Tags ein has_many ist: durch Verein):

So ist die Vereinigung von @Kaleidoscope eingerichtet ist infact richtig.

+0

Vielleicht ist dies wahr, wenn Sie 'build' verwenden, aber wie in der Frage beschrieben, verwende ich nicht' build', sondern 'new' und' save'. @ Kaleidoscope's Antwort ist nicht korrekt, da er 'inverse_of' in der anderen Richtung benutzt hat:' has_one: middle, dependent:: destroy, inverse_of:: right' – Undistraction

0

denke ich, dass es nicht funktioniert, weil Sie

has_many haben - has_one

Beziehung zwischen Links und Rechts statt

has_many - belongs_to

Auf der anderen Seite

belongs_to: links, durch: Mitte

ist nicht möglich. So sollten Sie Delegaten für Getter verwenden und schreiben Setter-Methode durch youself, so etwas wie diese

class Right < ActiveRecord::Base 
    has_one :middle, dependent: :destroy 
    delegate :left, to: :middle 

    def left=(left) 
    #logic 
    end 
end 
+0

Was ist falsch mit 'his_many, through' oder a'has_one, durch? Beide sind klar dokumentiert. – Undistraction

Verwandte Themen