Hier is een manier om het te modelleren. Laten we zeggen dat we een model 'Engagement' hebben met een start datetime, end datetime en naam. Een engagement heeft veel gebruikers, via een andere join-tabel genaamd 'user_engagements' (met bijbehorend UserEngagement-model). Dus we hebben
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
Nu hebben we een mooi eenvoudig schema. Een engagement modelleert in feite iets dat gebeurt, en user_engagements modelleert gebruikers die zijn geboekt om dat ding te doen. We hebben een veronderstelling (niet in de code geschreven) dat wanneer ze iets doen, ze niet beschikbaar zijn om iets anders te doen.
Onze volgende taak is het schrijven van een methode die gebruikers teruggeeft die beschikbaar zijn binnen een bepaalde tijdsperiode, dat wil zeggen een nieuwe opdracht. Dus we gaan een engagement aan en we willen alle gebruikers die geen engagement hebben dat overgaat in onze nieuwe engagement. Ik denk dat de eenvoudigste manier om dit te doen is om alle gebruikers te vinden die wel een cross-over-betrokkenheid hebben en vervolgens alle gebruikers terug te sturen die dat niet zijn. Als je begrijpt wat ik bedoel. Een preciezere manier om te zeggen dat e2 kruist met e1 is dat e2 begint voor het einde van e1 EN eindigt na het begin van e1.
Laten we dit een methode van een engagement-object maken, aangezien het volledig afhankelijk is van de gegevens van een engagement.
#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
Ik heb het gevoel dat er een efficiëntere manier is om dit in één query te krijgen, maar ik kan mijn vinger niet helemaal op de sql leggen.