모델을 작성하는 한 가지 방법이 있습니다. 우리는 'Engagement'라는 모델을 가지고 있는데,이 모델은 시작 날짜 시간, 종료 날짜 시간 및 이름을가집니다. 참여에는 'user_engagements'라는 다른 조인 테이블 (해당 UserEngagement 모델 포함)을 통해 많은 사용자가 있습니다. 그래서 우리는
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
우리는 멋진 간단한 스키마가 있습니다. 참여는 기본적으로 일어나는 일을 모델링하고 user_engagements는 그 일을하도록 예약 된 사용자를 모델링합니다. 우리는 무언가를하고있을 때 다른 일을 할 수 없다는 가정 (코드에 기록되어 있지 않음)을 가지고 있습니다.
우리의 다음 작업은 주어진 시간 내에 사용할 수있는 사용자, 즉 새로운 참여를 반환하는 메소드를 작성하는 것입니다. 따라서 우리는 참여를하고 새로운 참여로 교전을하지 않는 모든 사용자를 원합니다. 이 작업을 수행하는 가장 간단한 방법은 교차 사용 약정을 수행 한 모든 사용자를 찾아서 사용하지 않은 모든 사용자를 반환하는 것일 수 있습니다. 무슨 뜻인지 안다면. e2가 e1과 교차하는 것을 말하는 더 정확한 방법은 e2가 e1의 끝에서 시작하고 e1의 시작 후에 끝나는 것입니다.
참여도 데이터에 전적으로 의존하기 때문에 참여도 메소드의 메소드로 만듭니다.
#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
나는 한 가지 쿼리에서 이것을 얻는 더 효율적인 방법이있는 것처럼 느껴진다. 그러나 나는 그저 SQL에 손가락을 넣을 수 없다.
우수! 이것은 정확히 내가 뭘 찾고 있었는지, 내가 이것과 함께 얼마나 멀리 볼 수 있습니다. 고맙습니다 :) – amr