Rails has_many: durch Suche durch zusätzliche Attribute in Join Modell
-
03-07-2019 - |
Frage
New sowohl Ruby und Rails, aber ich bin Buch jetzt erzogen (die anscheinend nichts bedeutet, haha).
Ich habe zwei Modelle, Event-und Benutzer durch einen Tisch EventUser verbunden
class User < ActiveRecord::Base
has_many :event_users
has_many :events, :through => :event_users
end
class EventUser < ActiveRecord::Base
belongs_to :event
belongs_to :user
#For clarity's sake, EventUser also has a boolean column "active", among others
end
class Event < ActiveRecord::Base
has_many :event_users
has_many :users, :through => :event_users
end
Dieses Projekt ist ein Kalender, in dem ich den Überblick über die Menschen zu halten, habe die Anmeldung und ihren Namen für ein bestimmtes Ereignis Auskratzen. Ich stelle dar, die viele zu viele ist ein guter Ansatz, aber ich kann so etwas wie dies nicht tun:
u = User.find :first
active_events = u.events.find_by_active(true)
Weil Ereignisse haben nicht wirklich, dass zusätzliche Daten, die EventUser Modell tut. Und während ich tun konnte:
u = User.find :first
active_events = []
u.event_users.find_by_active(true).do |eu|
active_events << eu.event
end
Dies scheint „die Schienen Weg“ im Gegensatz zu sein. Kann mich jemand aufklären, das ist für mich eine lange Zeit heute Abend (heute morgen) nervt?
Lösung
Wie wäre es so etwas wie dies in Ihrem User-Modell hinzufügen?
has_many :active_events, :through => :event_users,
:class_name => "Event",
:source => :event,
:conditions => ['event_users.active = ?',true]
Danach Sie sollten in der Lage sein, aktiv Ereignisse nur für einen Benutzer zu erhalten, indem Aufruf:
User.first.active_events
Andere Tipps
Milan Novota hat eine gute Lösung - aber :conditions
ist veraltet und das :conditions => ['event_users.active = ?',true]
Bit scheint nicht nur sehr Schienen sowieso. Ich ziehe es so etwas wie folgt aus:
has_many :event_users
has_many :active_event_users, -> { where active: true }, class_name: 'EventUser'
has_many :active_events, :through => :active_event_users, class_name: 'Event', :source => :event
Danach sollten Sie noch in der Lage sein, aktiv Ereignisse nur für einen Benutzer zu erhalten, indem Aufruf:
User.first.active_events
Auch wenn Ihr u.events nicht explizit Aufruf der user_events Tabelle, die Tabelle immer noch in dem SQL enthalten ist implizit wegen der notwendigen verbindet. So können Sie immer noch die Tabelle in Ihrem Fund Bedingungen verwenden:
u.events.find(:all, :conditions => ["user_events.active = ?", true])
Natürlich, wenn Sie planen, zu tun dies viel Nachschlag dann sicher, geben Sie ihm einen separaten Verein wie Milan Novota schon sagt, aber es gibt keine Anforderung für Sie, es so zu tun
Nun, mehr Verantwortung wird in User
Modell setzen, als tatsächlich benötigt wird, und es gibt keinen guten Grund, dies zu tun.
Wir können zunächst den Umfang in EventUser
Modell definieren, da, wo es tatsächlich gehört, wie:
class EventUser < ActiveRecord::Base
belongs_to :event
belongs_to :user
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
end
Nun wird ein Benutzer beiden Arten von Veranstaltungen haben könnte: aktiv Veranstaltungen sowie inaktiver Ereignisse, so können wir die Beziehung in User
Modell wie folgt definieren:
class User < ActiveRecord::Base
has_many :active_event_users, -> { active }, class_name: "EventUser"
has_many :inactive_event_users, -> { inactive }, class_name: "EventUser"
has_many :inactive_events, through: :inactive_event_user,
class_name: "Event",
source: :event
has_many :active_events, through: :active_event_users,
class_name: "Event",
source: :event
end
Die Schönheit in dieser Technik ist, dass die Funktionalität ein aktive oder ein inaktives Ereignis zu sein gehört Modell EventUser
, und wenn in Zukunft geändert werden, die Funktionalität benötigt, wäre es nur an einer Stelle geändert werden: EventUser
Modell und die Änderungen werden in allen anderen Modellen berücksichtigt werden.