has_and_belongs_to_many vs has_many durch

76

Bitte erläutern Sie den Unterschied zwischen has_and_belongs_to_many und has_many durch eine Beziehung. Wann und wo welches verwenden?

Mohit Jain
quelle

Antworten:

108

Soweit ich mich erinnern kann, erhalten has_and_belongs_to_manySie eine einfache Nachschlagetabelle, die auf Ihre beiden Modelle verweist.

Zum Beispiel,

Geschichten können zu vielen Kategorien gehören. Kategorien können viele Geschichten haben.

Categories_Stories Table
story_id | category_id

has_many :through gibt Ihnen ein drittes Modell, in dem verschiedene andere Informationen gespeichert werden können, die zu keinem der Originalmodelle gehören.

Zum Beispiel

Person kann viele Zeitschriften abonnieren. Zeitschriften können viele Abonnenten haben.

Somit können wir ein Abonnementmodell in der Mitte haben, das uns eine ähnliche Tabelle wie im vorherigen Beispiel gibt, jedoch mit zusätzlichen Eigenschaften.

Subscriptions Table
person_id | magazine_id | subscription_type | subscription_length | subscription_date 

Und so weiter.

Dan
quelle
37
Beachten Sie, dass die Tabelle in alphabetischer Reihenfolge benannt werden muss, dh in der Tabelle "Kategorien_Geschichten" im Gegensatz zu "Geschichten_Kategorien" - dies ist die Konvention, mit der sie funktioniert.
Will
Danke, ich habe meinen Beitrag jetzt geändert
Dan
Warum müssen sie alphabetisch sein?
Ctilley79
@ ctilley79 das ist die verwendete Konvention. Wenn der Verein gegründet ist, weiß er, nach welcher Tabelle er suchen muss
Will
@ Will Ok. Ich werde es versuchen.
Ctilley79
39

Von http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

Die einfachste Faustregel lautet, dass Sie eine has_many: through-Beziehung einrichten sollten, wenn Sie mit dem Beziehungsmodell als unabhängige Entität arbeiten müssen. Wenn Sie mit dem Beziehungsmodell nichts tun müssen, ist es möglicherweise einfacher, eine Beziehung has_and_belongs_to_many einzurichten (obwohl Sie daran denken müssen, die Verknüpfungstabelle in der Datenbank zu erstellen). Sie sollten has_many: through verwenden, wenn Sie Validierungen, Rückrufe oder zusätzliche Attribute für das Join-Modell benötigen.

Tadas T.
quelle
3
Ich würde auch hinzufügen, dass es viele Methoden gibt, die Rails in has_and_belongs_to_many einfügen und nicht in has_many: through. Alle Methoden wie das Zuweisen einer Sammlung von Werten zur Zuordnung scheinen in der Dokumentation für has_many nicht aufgeführt zu sein: überguides.rubyonrails.org/…
e3matheus
15

Meine Faustregel lautet: Kann ich hier mit einer Liste von Kontrollkästchen auskommen? Wenn ja, dann ist es eine habtm Vereinigung. Wenn ich das Kontrollkästchen benötige, um mehr über die Beziehung zu erfassen als nur Ja / Nein, zu der sie gehört, verwenden Sie has_many: through. HABTM ist so einfach wie die Verwendung der _ids-Methode mit einer simple_form collection_check_boxes. Has_many: durch beinhaltet oft akzeptiert_nested_attributes_for.

Davidfurber
quelle
4

Sie sollten has_many: through verwenden, wenn Sie Validierungen, Rückrufe oder zusätzliche Attribute für das Join-Modell benötigen.

Andre Machado
quelle
2

Viele der Antworten klarstellen, dass Sie verwenden sollten , has_and_belongs_to_manygegen , has_many through:wenn Sie irgendwelche zusätzlichen Daten nicht brauchen oder Validierungen auf den Tisch kommen.

Allerdings , passen diesen Ansatz zu nehmen. In den frühen Phasen der Anwendungsentwicklung ist dies nahezu unmöglich zu wissen, welche zusätzlichen Funktionen oder Validierungen Sie in der fernen Zukunft des Projektlebenszyklus benötigen. Wenn Sie sich für die Verwendung has_and_belongs_to_manyentschieden haben und zwei Jahre später einen einfachen Datenpunkt oder eine einfache Validierung hinzufügen möchten, ist die Migration dieser Änderung äußerst schwierig und fehleranfällig. Aus Sicherheitsgründen standardmäßighas_many :through

RuboTrip
quelle
1
Können Sie erklären, warum dies gefährlich und fehleranfällig wäre? Ein HABTM ist dasselbe wie ein has_many: through, nur ohne das Modell. Sie können einen HABTM sehr elegant in einen obwohl konvertieren.
Grepsedawk
1
Hier ist eine gute Antwort auf Ihre Frage, @grepsedawk: flatironschool.com/blog/...
David Hempy
2

Nach meiner Erfahrung ist es immer besser zu verwenden, has_many: throughda Sie der Tabelle Zeitstempel hinzufügen können. Viele Male während einige Debug - ActiveRecordObjekte , die durch HABTM verbunden sind, mir fehlte created_at, updated_atZeitstempel den Schlüssel zu bekommen , was wirklich passiert ist . Denken Sie also daran, dass es Ihnen beim Debuggen und Untersuchen von Problemen mit Datenbeziehungen im Kontext der Zeit helfen kann, denn ohne sie sind Sie "blind", wenn Beziehungen erstellt oder aktualisiert wurden.

Yozzz
quelle