Angenommen, Sie haben ein Eins-zu-Viele-Beziehungsmodell, wie unten gezeigt.
class User
has_one :examinee
end
class Examinee
belongs_to :user
has_many :tests
end
class Test
belongs_to :examinee
end
Wie implementieren Sie es, wenn Sie das relevante Testmodell aus dem Benutzermodell erhalten möchten?
Es gibt verschiedene Möglichkeiten, dies zu tun, aber ich denke, Sie verwenden häufig die praktische Funktion "Delegieren" von ActiveRecord oder "has_many-through". Beide können erreichen, was Sie tun möchten, aber die ausgegebenen Abfragen unterscheiden sich geringfügig, sodass ich sie vorstellen werde.
delegate
Mit delegate können Sie eine Methode an eine andere Klasse delegieren. Weitere Informationen finden Sie im Rails Guide. 3.4.1 delegate
In diesem Fall implementieren Sie wie folgt.
app/models/user.rb
delegate :tests, to: :examinee
Bei der Ausführung werden zwei Abfragen ausgegeben, wie unten gezeigt. Rufen Sie zuerst den Prüfling des Delegierungsziels ab (erste Abfrage) und führen Sie dann Prüflingstests aus (zweite Abfrage).
irb> user.tests
Examinee Load SELECT `examinees`.* FROM `examinees` WHERE `examinees`.`user_id` = 1 LIMIT 1
Test Load SELECT `tests`.* FROM `tests` WHERE `tests`.`examinee_id` = 1
has_many-through
has_many-through wird häufig in vielen zu vielen Fällen verwendet, kann aber auch in Eins-zu-vielen-Fällen wie diesem verwendet werden.
Weitere Informationen finden Sie im Rails Guide. 2.4 has_many: durch Assoziation
In diesem Fall implementieren Sie wie folgt.
app/models/user.rb
has_many :tests, through: :examinee
Bei der Ausführung wird eine Abfrage wie unten gezeigt ausgegeben. In diesem Fall wird nur eine verknüpfte Abfrage ausgegeben. Wenn man bedenkt, dass diese Funktion so implementiert ist, dass sie vielen zu vielen entspricht, kann man verstehen, dass sie durch Join erfasst wird, da sie in zwei Schritten wie Deletgate nicht effizient erfasst werden kann.
irb> user.tests
Test Load SELECT `tests`.* FROM `tests` INNER JOIN `examinees` ON `tests`.`examinee_id` = `examinees`.`id` WHERE `examinees`.`user_id` = 1
Ob es besser ist, zwei Abfragen oder eine Abfrage zu verknüpfen, hängt von der Ausführungsumgebung ab. Daher kann nicht beurteilt werden, ob es gut oder schlecht ist. In den meisten Fällen spielt es keine Rolle, welche Sie schreiben, also spielt es keine Rolle, welche Sie schreiben.
Selbst wenn es aus Black-Box-Sicht so aussieht, als würde es dasselbe tun, können die intern ausgegebenen Abfragen wie diesmal unterschiedlich sein. Gelegentlich wäre es interessant, diese kleinen Unterschiede zu überprüfen, wenn man den Ursprung und den Zweck der Funktion betrachtet.
Recommended Posts