Самый быстрый способ - найти пробелы с помощью SQL-запроса. Однако это было бы сложно и плохо соответствовало модели ActiveRecord, поэтому следующий самый быстрый способ, которым я могу придумать, - это сортировать контракты в базе данных в хронологическом порядке и находить пробелы в Ruby, повторяя каждый результат и добавляя комнаты и даты в массив когда вы сталкиваетесь с ними.
Однако, если вам нужен более быстрый доступ к пробелам, или вы делаете много манипуляций с пробелами, или если эти пробелы являются в некотором смысле продаваемым «продуктом», вам может быть выгоднее использовать другую модель. Как насчет Slot
, который является минимально возможной продолжительностью контракта (например, один месяц)? Вы бы создали слоты для каждой комнаты и каждого месяца в течение следующих нескольких лет. Каждый из них имеет slot.available == true
для запуска, а обратный вызов after_save
модели Contract
устанавливает available = false
, где это необходимо. С помощью этой настройки вы могли бы легче определить свой пробел (Room.with_available_slots
):
class Contract < ActiveRecord::Base
has_many :slots
end
class Slot < ActiveRecord::Base
belongs_to :room
belongs_to :contract
end
class Room < ActiveRecord::Base
has_many :slots
has_many :contracts, :through => :slots
named_scope :with_available_slots,
:joins => :slots,
:conditions => {:slots => {:contract_id => nil}},
:select => "*, COUNT(*) AS num_slots",
:group => "room_id",
:having => "num_slots > 0"
end
В этом дизайне есть и другие полезные функции, такие как возможность предотвращения бронирования определенных дат, применение разных цен к определенным слотам и т. Д. Он не такой чистый, как ваш дизайн, но, по моему опыту, он лучше работает с реальными данными, поскольку исключения более легко обрабатываются.