#ruby-on-rails #ruby #lambda
Вопрос:
В номере есть много бронирований
Бронирование принадлежит номеру
У меня есть этот код, и он отлично работает:
available_rooms = Room.select {|room| room.bookings.where("day = ?", date).count < 3 || room.bookings.empty?}
но мне интересно, можно ли переписать его как лямбду с левым соединением
scope :available, lambda {|date| joins('LEFT OUTER JOIN bookings on bookings.room_id = rooms.id').......
Я попробовал это, но получил обратно только номера по крайней мере С одним Бронированием, поэтому полностью пустые номера БЕЗ каких-либо бронирований были исключены:
def self.available(date)
# You can use `Arel.star` instead of `:id` on postgres.
b = Booking.arel_table[:id]
group(:id)
.left_joins(:bookings)
.where(bookings: { day: date })
.having(b.count.lt(3)) # COUNT(bookings.id) < 3
end
Комментарии:
1. Спасибо! Но в этом случае я получу только те номера, которые забронированы на эту дату. Что мне нужно — все номера, которые вообще не забронированы на эту дату номера, которые забронированы на эту дату, но общая сумма этих бронирований составляет
2. Может быть, вы могли бы добавить в свой запрос предложение «иметь» и «группа»?
.having("COUNT(date) < 3").group(:id)
Ответ №1:
ОБНОВЛЕНИЕ Для удовлетворения требования вам действительно понадобится сложное соединение, пожалуйста, попробуйте вместо этого следующее
class Room < ApplicationRecord
def self.available(date)
b = Booking.arel_table
join_statement = Arel::Nodes::OuterJoin.new(b,
Arel::Nodes::On.new(
arel_table[:id].eq(b[:room_id])
.and(b[:day].eq(Arel::Nodes.build_quoted(date)))
))
group(:id)
.joins(join_statement)
.having(b[:id].count.lt(3))
end
end
Здесь нам остается присоединиться bookings
в зависимости от отношения к комнате и запрошенной даты. Теперь, если номер не забронирован на эту дату или у него менее 3 бронирований на эту дату, он должен появиться в соответствии с запросом.
Комментарии:
1. Спасибо за помощь! @engineersmnky Это почти работает, но в данном случае у меня есть: — все свободные номера (без бронирования вообще) — все номера с бронированием на НЕКОТОРУЮ дату с общей суммой
2. @Ирина Я вижу. Обновлено соответственно с 2-м условием присоединения.
3. Еще раз спасибо вам! Я получаю эту ошибку, на самом деле не могу найти проблему… «SQLite3::Исключение SQLException: неоднозначное имя столбца: main.rooms.id»
4. @Ирина Я понятия не имею, как это можно считать двусмысленным, мне кажется, это полностью соответствует требованиям. Также я бы настоятельно рекомендовал использовать готовую к работе базу данных, например PostgreSQL, MySQL, MariaDB, MSSQL и т.д. У SQLite много причуд, с большинством из которых я недостаточно знаком, чтобы действительно быть в состоянии оказать адекватную помощь.