You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails如何将可用客房查询改写为带左连接的lambda作用域

问题出在你把日期过滤条件写在了全局WHERE子句中:左连接后没有对应日期预订的客房,关联出来的bookings相关字段都是NULL,WHERE bookings.day = ? 会直接把这些NULL值的行过滤掉,导致完全没有预订记录的空房被排除。

你需要把日期过滤条件移到左连接的关联条件中,这样左连接仅会匹配指定日期的预订记录,没有匹配预订的客房仍然会保留在结果集中,COUNT(bookings.id)统计值为0,自然满足小于3的筛选要求,不需要额外判断空预订的情况。

正确的scope实现

scope :available, lambda { |date|
  left_joins("LEFT OUTER JOIN bookings ON bookings.room_id = rooms.id AND bookings.day = ?", date)
    .group("rooms.id")
    .having("COUNT(bookings.id) < 3")
}

如果你偏好使用Arel避免硬写SQL,可以用更安全的版本:

scope :available, lambda { |date|
  rooms = Room.arel_table
  bookings = Booking.arel_table

  join_on = rooms[:id].eq(bookings[:room_id]).and(bookings[:day].eq(date))
  joins(rooms.join(bookings, Arel::Nodes::OuterJoin).on(join_on).join_sources)
    .group(rooms[:id])
    .having(bookings[:id].count.lt(3))
}

两种写法执行逻辑完全一致:

  • 左连接时就限定只关联对应日期的预订记录
  • 按客房ID分组后统计每个客房的匹配预订数
  • 筛选出预订数小于3的客房,其中预订数为0的空房自然会被包含在结果中

内容的提问来源于stack exchange,提问作者Irina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:48:01