Neu für Ruby und Rails, aber ich bin inzwischen in einem Buch ausgebildet (was anscheinend nichts bedeutet, haha).
Ich habe zwei Modelle, Event und User, die über eine Tabelle EventUser verbunden sind
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 nachverfolgen muss, wie sich Leute für eine bestimmte Veranstaltung anmelden und ihren Namen auskratzen. Ich denke, dass viele zu viele ein guter Ansatz sind, aber ich kann so etwas nicht tun:
u = User.find :first
active_events = u.events.find_by_active(true)
Da Ereignisse diese zusätzlichen Daten nicht haben, ist dies beim EventUser-Modell der Fall. 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 dem "Schienenweg" zu widersprechen. Kann mich jemand aufklären, das nervt mich heute Abend (heute Morgen) schon lange?
ruby-on-rails
ruby
has-many
has-many-through
Stefan Mai
quelle
quelle
Antworten:
Wie wäre es, wenn Sie Ihrem Benutzermodell so etwas hinzufügen?
has_many :active_events, :through => :event_users, :class_name => "Event", :source => :event, :conditions => ['event_users.active = ?',true]
Danach sollten Sie in der Lage sein, aktive Ereignisse für einen Benutzer zu erhalten, indem Sie einfach Folgendes aufrufen:
quelle
-> { where event_users: { active: true } }
event_users
Bereich definiert wird ? Wiescope :active, where(:active => true)
? (mit Rails 3.2)has_many through:
? Könnten Sie das gesamte Rails 4-spezifische Äquivalent einschließen?Milan Novota hat eine gute Lösung - ist aber
:conditions
jetzt veraltet und das:conditions => ['event_users.active = ?',true]
Stück scheint sowieso nicht sehr schienen zu sein. Ich bevorzuge so etwas: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 weiterhin in der Lage sein, aktive Ereignisse für einen Benutzer abzurufen, indem Sie Folgendes aufrufen:
quelle
:conditions => {active: true}
. Arbeitete für mich, danke!Auch wenn Ihre u.events die Tabelle user_events nicht explizit aufrufen, ist diese Tabelle aufgrund der erforderlichen Verknüpfungen implizit in SQL enthalten . Sie können diese Tabelle also weiterhin in Ihren Suchbedingungen verwenden:
u.events.find(:all, :conditions => ["user_events.active = ?", true])
Natürlich gäbe ihm , wenn Sie viel diese Lookup zu tun , dann sicher planen, einen separaten Verein wie Milan Novota schon sagt, aber es gibt keine Anforderung für Sie , es so zu tun
quelle
Nun, es wird mehr Verantwortung in das
User
Modell eingebracht, als tatsächlich benötigt wird, und es gibt keinen guten Grund dafür.Wir können den Umfang zuerst im
EventUser
Modell definieren, weil dort, wo er tatsächlich hingehört, wie:class EventUser < ActiveRecord::Base belongs_to :event belongs_to :user scope :active, -> { where(active: true) } scope :inactive, -> { where(active: false) } end
Jetzt kann ein Benutzer beide Arten von Ereignissen haben: aktive Ereignisse sowie inaktive Ereignisse, sodass wir die Beziehung im
User
Modell wie folgt definieren können: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
Das Schöne an dieser Technik ist, dass die Funktionalität, ein aktives oder ein inaktives Ereignis zu sein
EventUser
, zum Modell gehört. Wenn die Funktionalität in Zukunft geändert werden muss, wird sie nur an einer Stelle geändert:EventUser
Modell, und die Änderungen werden reflektiert alle anderen Modelle.quelle