Aqui está uma maneira de modelá-lo. Digamos que temos um modelo 'Engagement' que tem uma data e hora de início, uma data e hora de término e um nome. Um engajamento tem muitos usuários, por meio de outra tabela de junção chamada 'user_engagements' (com o modelo UserEngagement correspondente). Então nós temos
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
Agora temos um bom esquema simples. Um engajamento basicamente modela algo que está acontecendo, e user_engagements modela usuários que estão agendados para fazer isso. Temos uma suposição (não escrita no código) de que, quando eles estão fazendo algo, não estão disponíveis para fazer mais nada.
Nossa próxima tarefa é escrever um método que retorne usuários disponíveis em um determinado período de tempo, ou seja, um novo engajamento. Então, fazemos um engajamento e queremos todos os usuários que não têm um engajamento que cruze com o nosso novo engajamento. Acho que a maneira mais simples de fazer isso pode ser encontrar todos os usuários que têm um engajamento de crossover e, em seguida, retornar todos os usuários que não são eles. Se você souber o que quero dizer. Uma maneira mais precisa de dizer que e2 cruza com e1 é que e2 começa antes do final de e1 E termina após o início de e1.
Vamos fazer disso um método de um objeto de engajamento, pois é totalmente dependente dos dados de um engajamento.
#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
Eu sinto que há uma maneira mais eficiente de obter isso em uma consulta, mas não consigo colocar meu dedo no sql.