Rails has_many: tramite Trova per attributi aggiuntivi in ​​Join Model

Nuovo sia per Ruby che per Rails ma sono ormai istruito (che apparentemente non significa nulla, haha).

Ho due modelli, Event e User uniti tramite una tabella EventUser

class User  :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  :event_users end 

Questo progetto è un calendario in cui devo tenere traccia delle persone che si iscrivono e che scrivono il loro nome per un dato evento. Immagino che molti a molti siano un buon approccio, ma non posso fare qualcosa del genere:

 u = User.find :first active_events = u.events.find_by_active(true) 

Poiché gli eventi in realtà non hanno questi dati extra, il modello EventUser lo fa. E mentre potevo fare:

 u = User.find :first active_events = [] u.event_users.find_by_active(true).do |eu| active_events << eu.event end 

Questo sembra essere contrario al “modo delle rotaie”. Qualcuno mi può illuminare, questo mi ha tormentato a lungo stasera (stamattina)?

Che ne dici di aggiungere qualcosa di simile al tuo modello utente?

 has_many :active_events, :through => :event_users, :class_name => "Event", :source => :event, :conditions => ['event_users.active = ?',true] 

Dopodiché dovresti essere in grado di ottenere eventi attivi per un utente semplicemente chiamando:

 User.first.active_events 

Milano Novota ha una buona soluzione – ma :conditions sono ormai deprecate e il :conditions => ['event_users.active = ?',true] bit non sembra comunque molto rotaie. Preferisco qualcosa del genere:

 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 

Dopodiché dovresti comunque essere in grado di ottenere eventi attivi per un utente semplicemente chiamando:

 User.first.active_events 

Anche se u.events non sta chiamando esplicitamente la tabella user_events, quella tabella è ancora inclusa in SQL implicitamente a causa dei join necessari. Quindi, puoi ancora usare quella tabella nelle tue condizioni di ricerca:

 u.events.find(:all, :conditions => ["user_events.active = ?", true]) 

Certo, se hai intenzione di fare questa ricerca molto di sicuro, dai una associazione separata come suggerisce Milan Novota, ma non è necessario per te farlo in quel modo

Bene, più responsabilità viene posta nel modello User rispetto a quella effettivamente necessaria e non ci sono buoni motivi per farlo.

Possiamo prima definire l’ambito nel modello EventUser perché dove effettivamente appartiene, come:

 class EventUser < ActiveRecord::Base belongs_to :event belongs_to :user scope :active, -> { where(active: true) } scope :inactive, -> { where(active: false) } end 

Ora, un utente può avere entrambi i tipi di eventi: eventi attivi e eventi inattivi, quindi possiamo definire la relazione nel modello User come segue:

 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 

Il bello in questa tecnica è che la funzionalità di essere un evento attivo o inattivo appartiene al modello EventUser e se in futuro la funzionalità deve essere modificata, verrà modificata solo in un unico punto: il modello EventUser e le modifiche saranno riflessa in tutti gli altri modelli.