Ich versuche zu verstehen, was has_many :through
und wann ich es verwenden soll (und wie). Ich verstehe es jedoch nicht. Ich lese Beginning Rails 3 und habe versucht zu googeln, kann es aber nicht verstehen.
Ich versuche zu verstehen, was has_many :through
und wann ich es verwenden soll (und wie). Ich verstehe es jedoch nicht. Ich lese Beginning Rails 3 und habe versucht zu googeln, kann es aber nicht verstehen.
Antworten:
Angenommen, Sie haben zwei Modelle: User
und Group
.
Wenn Sie möchten, dass Benutzer zu Gruppen gehören, können Sie Folgendes tun:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
Was ist, wenn Sie zusätzliche Metadaten rund um die Assoziation verfolgen möchten? Zum Beispiel, wenn der Benutzer der Gruppe beigetreten ist oder welche Rolle der Benutzer in der Gruppe spielt?
Hier machen Sie die Assoziation zu einem erstklassigen Objekt:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
Dadurch wird eine neue Tabelle eingeführt und die group_id
Spalte aus der Benutzertabelle entfernt.
Das Problem mit diesem Code ist, dass Sie jeden anderen Ort, an dem Sie die Benutzerklasse verwenden, aktualisieren und ändern müssen:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
Diese Art von Code ist zum Kotzen und macht das Einführen solcher Änderungen schmerzhaft.
has_many :through
gibt Ihnen das Beste aus beiden Welten:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
Jetzt können Sie es wie ein normales behandeln has_many
, aber Sie können das Assoziationsmodell bei Bedarf nutzen.
Beachten Sie, dass Sie dies auch mit tun können has_one
.
Bearbeiten: Erleichtert das Hinzufügen eines Benutzers zu einer Gruppe
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user.groups << group
? Oder wird alles von diesem Verein erledigt?
Angenommen, Sie haben diese Modelle:
Car
Engine
Piston
Ein Auto has_one :engine
Ein Motor belongs_to :car
Ein Motor has_many :pistons
Kolbenbelongs_to :engine
Ein has_many :pistons, through: :engine
Autokolbenhas_one :car, through: :engine
Im Wesentlichen delegieren Sie eine Modellbeziehung an ein anderes Modell, sodass car.engine.pistons
Sie dies einfach tun müssen , anstatt anrufen zu müssencar.pistons
has_many :through
und has_and_belongs_to_many
Beziehungen funktionieren über eine Verknüpfungstabelle , bei der es sich um eine Zwischentabelle handelt, die die Beziehung zwischen anderen Tabellen darstellt. Im Gegensatz zu einer JOIN-Abfrage werden Daten tatsächlich in einer Tabelle gespeichert.
Mit has_and_belongs_to_many
benötigen Sie keinen Primärschlüssel und greifen über ActiveRecord-Beziehungen und nicht über ein ActiveRecord-Modell auf die Datensätze zu. Normalerweise verwenden Sie HABTM, wenn Sie zwei Modelle mit einer Viele-zu-Viele-Beziehung verknüpfen möchten.
Sie verwenden eine has_many :through
Beziehung, wenn Sie mit der Verknüpfungstabelle als Rails-Modell interagieren möchten. Dazu gehören Primärschlüssel und die Möglichkeit, den verknüpften Daten benutzerdefinierte Spalten hinzuzufügen. Letzteres ist besonders wichtig für Daten, die für die verknüpften Zeilen relevant sind, aber nicht wirklich zu den zugehörigen Modellen gehören - beispielsweise zum Speichern eines berechneten Werts, der aus den Feldern in der verknüpften Zeile abgeleitet wird.
In einem Handbuch zu aktiven Datensatzzuordnungen lautet die Empfehlung:
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.
user
Modell eine Methode hinzufügen, um die Gruppe hinzuzufügen. So etwas wie die Bearbeitung, die ich gerade gemacht habe. Hoffe das hilft.