5

Die Rails 4 Dokumentation sagt in Bezug auf diese Rückrufe auf dem Modell für eine Beziehung has_many :through beitreten zerstören:Warum ist collection = Objekte auf has_many nicht: durch Auslösen von Rückrufen auf dem Join-Modell beim Löschen der Assoziation?

collection=objects Ersetzt die Sammlungen Inhalt durch das Löschen und Objekte entsprechend hinzufügen. Wenn die Option: through aktiviert ist, werden Callbacks in den Join-Modellen ausgelöst, mit Ausnahme von Callbacks löschen, , da das Löschen direkt erfolgt.

Zum Glück ist es zumindest dokumentiert, aber ich möchte wissen, warum in aller Welt dies der Fall ist? Hoffentlich gibt es einen technischen Grund, denn sonst ist es einfach verrückt!

In meinem Fall hatte ich eine has_and_belongs_to_many Beziehung auf dem Join-Tabellen-Modell zu einem anderen Modell. Die Datensätze in dieser zweiten Join-Tabelle werden niemals gelöscht, wenn die zugehörigen Datensätze in der ersten Join-Tabelle gelöscht wurden. Ich griff dies auf die Hacky fühlt, und ich muss mich wiederholen Sie auf jeder Seite der :through Beziehung:

has_many :schools_templates, dependent: :destroy 
has_many :templates, through: :schools_templates, before_remove: :remove_groups_school_templates 

private 

def remove_groups_school_templates(template) 
    schools_templates.where(template: template).first.groups.clear 
end 

Es gibt eine Validierung ‚sicherstellen‘ Einzigartigkeit auf den Tabellen Datensätze zwischen den beiden Fremdschlüssel verbinden, so dass das, warum kann ich first im Rückruf anrufen.

Antwort

0

So lief ich das gleiche Problem neulich neu. In meinem Fall habe ich etwas getan, was dem ähnlich war, was Sie getan haben, und stieß auf das gleiche Problem mit der Join-Tabelle, die gelöscht anstatt zerstört wurde.

Ich fing an, den Code durchzusehen und ich glaube, dass die Dokumentation gerade veraltet ist. has_many_through_association

Sie müssen nur das abhängige:: destroy zur has_many: through-Beziehung hinzufügen.

class User 
    has_many :partnerships, dependent: :destroy 
    has_many :partners, through: :partnerships, dependent: :destroy 
end 

Der Schmerz, den ich es zu tun hatte war:

user.partner_ids = [1,2,3] 
#creates the relationships 
user.partner_ids = [] 
#was deleting the records from partnerships without callbacks. 

Die abhängige: zerstören auf der Beziehung, die festen Partner. Callbacks werden jetzt ausgeführt und die Dinge sind wieder gut.

2

Normalerweise setzen Sie dependent: :destroy da, wenn man etwas über has_many Verein löschen wollen:

class User 
    has_many :partnerships, dependent: :destroy 
    has_many :partners, through: :partnerships 
end 

Wenn Sie partners sowie Partnerschaften zerstören wollen Sie diese Abhängigkeit Partnership s Modell hinzufügen:

class Partnership 
    belongs_to :partner, dependent: :destroy 
    belongs_to :user 
end 

Wenn das Objekt zerstört wird, ruft es den Befehl destroy für jedes Objekt auf, in dem die Destroy-Abhängigkeit bereitgestellt wird. So ruft User Anrufe auf jeder Partnership, und jede Partnership Anrufe zerstören auf jeder Partner.

"Warum kann nicht mit through verwendet werden" - nun, die Antwort ist "da Löschung ist direkt". Ich weiß, dass es nicht viel sagt (für mich auch nicht), aber auf der anderen Seite ist es für mich eine schlechte Idee, Abhängigkeiten zu Objekten hinzuzufügen, die nicht direkt verlinkt sind. Betrachten Sie das obige Beispiel: Wenn dependant - destroy auf Partnern funktioniert und sie zerstört - sollte es auch das Join-Modell zerstören? Sicherlich ja, denn in einem anderen Fall wird es zu Datenkorruption kommen, aber Sie können einige Daten verlieren, die im Join-Modell liegen könnten, also in einigen Fällen - nein, Sie wollen das Join-Modell nicht zerstören. Dies bedeutet, dass das Rails-Team den neuen Parameter delete_join hinzufügen muss, um anzugeben, ob das Modell gespeichert werden soll oder nicht. Und das ist nur ein schlechtes Design, da wir schon bessere Ansätze haben - fügen Sie Abhängigkeiten in die Join-Modelle ein.

+0

Danke für Ihre Antwort :) Ich habe die Frage aktualisiert, um zu zeigen, dass ich bereits die abhängige Zerstörung auf die Verknüpfung mit dem Join-Modell gesetzt hatte. Nicht sicher, warum ich das verpasst habe :) Ich denke, mein Argument ist, dass das Löschen nicht "direkt" sein sollte, sondern "Destroy" Callbacks auf dem Join-Modell auslösen sollte. –