Вот один из способов его моделирования.Допустим, у нас есть модель «Обручение», которая имеет дату начала, дату окончания и имя.У участия есть много пользователей через другую таблицу соединений, называемую 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.
Давайте сделаем это методом объекта взаимодействия, поскольку он полностью зависит от объекта взаимодействияdata.
#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.