Domanda

Nuovo sia per Ruby che per Rails, ma ormai sono istruito sul libro (che apparentemente non significa niente, ahah).

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

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

Questo progetto è un calendario, in cui devo tenere traccia delle persone che si iscrivono e grattano il loro nome per un determinato evento. Immagino che molti a molti sia 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 quei dati extra, il modello EventUser lo fa. E mentre potrei 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 di binari". Qualcuno può illuminarmi, questo mi ha infastidito per molto tempo stanotte (stamattina)?

È stato utile?

Soluzione

Che ne dici di aggiungere qualcosa di simile nel 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

Altri suggerimenti

Milano Novota ha una buona soluzione & # 8211; ma : condizioni è ora deprecato e : condizioni = > ['event_users.active =?', true] bit non sembra comunque molto rotaia. 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 essere ancora in grado di ottenere eventi attivi per un utente semplicemente chiamando:

User.first.active_events

Anche se u.events non sta esplicitamente chiamando la tabella user_events, quella tabella è comunque 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])

Ovviamente, se hai intenzione di fare molto questa ricerca, assicurati di dargli un'associazione separata come suggerisce Milan Novota, ma non c'è requisito per farlo in questo modo

Bene, nel modello User è stata assegnata una maggiore responsabilità di quella effettivamente necessaria e non vi sono buoni motivi per farlo.

Possiamo innanzitutto definire l'ambito nel modello EventUser perché a cui appartiene effettivamente, 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 potrebbe avere entrambi i tipi di eventi: eventi attivi ed 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 di questa tecnica è che la funzionalità di essere un evento attivo o inattivo appartiene al modello EventUser , e se in futuro la funzionalità dovesse essere modificata, sarebbe modificata solo in uno place: EventUser e le modifiche si rifletteranno in tutti gli altri modelli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top