Active has_n Verein
-
03-07-2019 - |
Frage
Ich frage mich, was der beste Weg, um eine Beziehung zu modellieren, wo ein Objekt mit genau n Objekten einer anderen Klasse zugeordnet ist. Ich mag die has_one Beziehung auf einen bestimmten Wert von n erweitern.
Zum Beispiel würde ein TopFiveMoviesList zu Benutzern gehört und hat genau fünf Filme. Ich könnte mir vorstellen, dass die zugrunde liegenden SQL-Tabellenfelder haben würden wie movie_id_1, movie_id_2, ... movie_id_5.
Ich weiß, ich könnte eine has_many Beziehung tun und die Zahl der Kinder auf Modellebene begrenzen, aber ich möchte lieber nicht einen Vermittler Tisch.
Lösung
Mein erster Instinkt wäre, einen Tisch kommen, aber wenn das nicht wünschenswert User.movie[1-5]_id
Spalten die Rechnung passen würden. (Ich denke, movie1_id
paßt besser mit Rails-Konvention als movie_id_1
.)
Da Sie diese Rails und Active markiert, werde ich etwas völlig ungetestet und wahrscheinlich etwas falsch Modell-Code auf meine Antwort hinzuzufügen. :)
class User < ActiveRecord::Base
TOP_N_MOVIES = 5
(1..TOP_N_MOVIES).each { |n| belongs_to "movie#{n}".to_sym, :class_name => Movie }
end
Sie können diese Zeile in einer Makro-Stil Methode wickeln, aber es sei denn, wenn es das ist ein gemeinsames Muster für Ihre Anwendung, das zu tun wird wahrscheinlich nur den Code, dass härter mit wenig DRY Nutzen zu lesen.
Sie möchten vielleicht auch Validierungen hinzufügen, um sicherzustellen, dass es keine doppelten Filme auf einem Benutzerliste enthalten sind.
Verknüpfen Sie Ihre Film-Klasse an den Benutzer zurück ist ähnlich.
class Movie < ActiveRecord::Base
(1..User::TOP_N_MOVIES).each do |n|
has_many "users_list_as_top_#{n}".to_sym, :class_name => User, :foreign_key => "movie#{n}_id"
end
def users_list_as_top_anything
ary = []
(1..User::TOP_N_MOVIES).each {|n| ary += self.send("users_list_as_top_#{n}") }
return ary
end
end
(Natürlich, die users_list_as_top_anything
wahrscheinlich besser als expliziten SQL geschrieben werden würden. Ich bin faul heute.)
Andere Tipps
Ich denke, die Umsetzung dieses Modells durch ein Join-Modell Sie sind beste Wette hier sein wird. Es ermöglicht das List
Modell über Listenlogik und Movie
Modell zu befürchten Film Logik zu kümmern. Sie können einen Nomination
erstellen (Name nicht der größte, aber Sie wissen, was ich meine) Modell, das die Beziehung zwischen Film und Listen zu handhaben, und wenn eine Grenze von 5 da ist, könnten Sie einfach die Anzahl der Nominierungen begrenzen Sie zurück ziehen.
Es gibt ein paar Gründe, warum ich denke, dieser Ansatz besser ist.
Als erstes vorausgesetzt, Sie wollen die Beziehungen zu durchqueren können, in beiden Richtungen (movie.lists
und list.movies
), der 5-Säule Ansatz wird viel chaotischer sein.
Während es so wäre viel besser für Active has n
Beziehungen zu unterstützen, tut es nicht, und so werden Sie auf, dass man den Rahmen kämpfen. Auch scheint die has n
Beziehung ein bisschen spröde ich in dieser Situation. Ich habe nicht diese Art der Umsetzung gesehen in Active abziehbar, obwohl ich es geschehen zu sehen, wirklich interessiert sein würde. :)
Ich nehme an, Sie „implementieren“ und nicht als „Modell“ verstehen? Die Modellierung ist ziemlich einfach, in UML, sagen, wo Sie eine Person Unternehmen haben, die aus 5 Filmeinheiten hergestellt wird.
Aber die Schwierigkeit kommt, wenn man has_one sagen, has_5 gehen. Wenn es ein einfacher skalar Wert ist, has_one ist vielleicht eine Eigenschaft auf der übergeordneten Einheit. Has_5 ist wahrscheinlich 2 miteinander durch eine kontrollierte Unternehmen Beziehung in UML „setzt sich zusammen aus“.
Die wichtigste Frage zu beantworten, ist wahrscheinlich: „Können Sie garantieren, dass es immer‚Top 5‘sein?“ Wenn ja, Modell mit Spalten, wie Sie bereits erwähnt. Wenn nein, Modell es mit einem anderen Unternehmen.
Eine andere Frage ist vielleicht: „Wie leicht wird es Refactoring sein?“ Wenn es einfach ist, Heck, mit 5 Spalten beginnen und Refactoring Einheiten zu trennen, wenn es jemals ändert.
Wie üblich „beste“ ist abhängig von dem geschäftlichen und technischen Umfeld.