Zde je jeden způsob, jak to modelovat. Řekněme, že máme model 'Engagement', který má počáteční datum, čas a datum ukončení a název. Zapojení má mnoho uživatelů prostřednictvím další tabulky spojení s názvem 'user_engagements' (s odpovídajícím modelem UserEngagement). Takže máme
User
has_many :user_engagements
has_many :engagements, :through => :user_engagements
Engagement
#fields - starts_at, ends_at (both datetime)
has_many :user_engagements
has_many :users, :through => :user_engagements
UserEngagement
belongs_to :user
belongs_to :engagement
Nyní máme pěkné jednoduché schéma. Interakce v podstatě modeluje něco, co se děje, a user_engagements modelují uživatele, kteří jsou k této věci rezervováni. Máme předpoklad (nezapsaný v kódu), že když něco dělají, nemohou dělat nic jiného.
Naším dalším úkolem je napsat metodu, která vrátí uživatele dostupné v daném časovém období, tedy nové zapojení. Takže jsme se zapojili a chceme, aby všichni uživatelé, kteří nemají zapojení, se kříží s naším novým zapojením. Myslím, že nejjednodušším způsobem, jak toho dosáhnout, by mohlo být najít všechny uživatele, kteří mají interakci s přechodem, a poté vrátit všechny uživatele, kteří jimi nejsou. Jestli víš co myslím. Přesnější způsob, jak říci, že e2 se kříží s e1, je, že e2 začíná před koncem e1 A končí po začátku e1.
Udělejme z toho metodu objektu zakázky, protože je zcela závislá na datech zakázky.
#in Engagement
def unavailable_user_ids
User.find(:all, :include => [:user_engagements], :select => "users.id", :conditions => ["user_engagements.starts_at < ? and user_engagements.ends_at > ?", self.ends_at, self.starts_at]).collect(&:id)
end
def available_users
User.find(:all, :conditions => ["id not in (?)", self.unavailable_user_ids])
end
Cítím, že existuje efektivnější způsob, jak to získat v jednom dotazu, ale nemohu tak docela položit prst na sql.