【问题标题】:SQL query rails, how to filter our current reservationSQL查询rails,如何过滤我们当前的预订
【发布时间】:2020-01-10 11:03:31
【问题描述】:

对于酒店应用程序,我试图过滤掉给定到达和离开日期的所有可用住宿,因此用户只会将这些视为选项。

我目前的做法是首先确定所有不可用的住宿,然后从所有住宿中扣除它们。

问题

当我想编辑预订时,我想:

  • 在评估可用住宿时排除当前预订

==> 所以在 @unavailable_accommodations 中,reservation.arrivalreservation.departure 的预订及其住宿不在查询语句中评估

这是否可能,或者我如何才能在不考虑当前的 reservation.accommodation 的情况下只为送礼者抵达和离开时获得可用的住宿?

期望结果示例

  • 说从 1 月 1 日到 1 月 2 日的预订_1 预订住宿_1。
  • 然后是reservation_2,从1月5日到1月6日预订住宿_1。
  • 当我随后编辑 reservation_1 并将出发时间更改为 1 月 6 日时,住宿_1 应该被标记为预订_2 已预订此住宿

代码

型号

class Reservation < ApplicationRecord
  belongs_to :hotel
  belongs_to :accommodation
end

class Accommodation < ApplicationRecord
  belongs_to :accommodation_category
  has_many :reservations, dependent: :destroy
  accepts_nested_attributes_for :accommodation_category
end

class Hotel < ApplicationRecord
  has_many :accommodation_categories, dependent: :destroy
  has_many :accommodations, through: :accommodation_categories
  has_many :reservations, dependent: :destroy
end

查询

@unavailable_accommodations = Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, departure)
.or(Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival >= ? AND ? >= reservations.departure", arrival, departure)).distinct

控制器动作


def accommodations_availability
#check if there was an accommodation for this reservation
    if !params[:reservation].nil?
      reservation = Reservation.find(params[:reservation])
      @prev_accommodation = reservation.accommodation
      @previous_cat = @prev_accommodation.accommodation_category
    end
    hotel = Hotel.includes(:accommodations).find(params[:id])
    arrival = Date.parse(accommodation_params[:arrival])
    departure = Date.parse(accommodation_params[:departure])
    time_span = arrival..departure

    #SQL statement
    @unavailable_accommodations = Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, departure)
    .or(Accommodation.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival >= ? AND ? >= reservations.departure", arrival, departure)).distinct


    @hotel_cats = hotel.accommodation_categories
    @hotel_accos = Accommodation.where(accommodation_category: @hotel_cats)
    @accommodations = @hotel_accos - @unavailable_accommodations
    @available_cats = []
    @accommodations.each do |acco|
      if !@available_cats.include? acco.accommodation_category
        @available_cats << acco.accommodation_category
      end
    end

    respond_to do |format|
      format.js
    end
  end

【问题讨论】:

  • “Accommodation.joins(:reservations).where.not(reservations: { id: current_reservation_id })”怎么样?
  • @Jean-MichelGigault,感谢您的回复。它应该包括当前预订,因为当前预订的日期应该在编辑中可用。
  • 好的,我认为这是您的设计的问题,即您在查询中计算available_accommodations,但您实际向用户显示的是available_reservations。这就是为什么在脑海中想象这个问题是如此令人困惑的原因。我希望你从这个角度思考。您不一定需要更改设计(您可以向用户显示可用的住宿,但查询应该更多关于幕后的预订)。
  • @ARK,使用了您建议的方法,并从 all_reservations 开始,有重叠,因此对其进行迭代以获得住宿。谢谢!
  • 顺便说一句,你是一个非常好的 stackoverflow 用户;中肯的问题,提供所有细节,耐心等待你自己的问题,开始赏金,用提示和想法自己找到解决方案,即我们一起构建了解决方案。这就是社区的全部意义所在。对我们取得的成就感到满意,虽然没有那么复杂:)

标签: sql ruby-on-rails


【解决方案1】:

为什么不简单地这样做:

@current_reservation = Reservation.find(params[:id]) # whatever it is
@unavailable_accommodations = your_query1
@available_accommodations = your_query2 - [@current_reservation.accommodation]

更新:

在控制器端可以有解决方案,但我觉得这种事情也应该在前端处理。

建议:在填写更新表单时,您如何传递 current_accommodation 的上一次预订出发和下一次预订到达。这样,您可以通过向两者添加最小值和最大值来限制编辑 TimeDate 字段。我希望你能明白。

从设计(安全)的角度来看,添加后端检查仍然很重要。我会考虑更多并再次更新,希望:)

更新 2:(在问题下方评论)

“好的,我认为这是您的设计的问题,即您正在计算查询中的 available_accommodations 但您实际向用户显示的内容是 available_reservations。这就是为什么将问题可视化如此令人困惑的原因。我希望您从这个角度思考。您不一定需要更改设计(您可以向用户显示可用的住宿,但查询应该更多关于幕后的预订)。”

【讨论】:

  • 感谢您的回复。这是行不通的。从 1 月 1 日到 1 月 2 日说 reservation_1 书籍 accommodation_1。然后是 reservation_2 从 1 月 5 日到 1 月 6 日书籍 accommodation_1。当我随后编辑 reservation_1 并将 departure 更改为 1 月 6 日时, accommodation_1 仍然会被标记为可用,即使很艰难 reservation_2 已经预订了这个住宿。
  • 我从您的评论中了解到,您希望阻止用户更新预订,如果它落在另一个预订上。在这种情况下,您还应该传递@reservations@available_accommodations,并且住宿应显示“未预订”日期可用而不是全部开放。我错过了什么吗?
  • 澄清:如果有人想编辑预订并填写不同的抵达或离开日期,显示的控制器操作将用于查找这些新的抵达和离开日期的所有可用住宿。
  • 你能在这里分享你的控制器操作代码吗(你在哪里调用这个查询)。我认为问题就在那里。我现在完全理解你的要求了。只需要看代码。
  • 好的,会添加的。
【解决方案2】:

您可以在一个查询中直接过滤掉所有可用的住宿:

@available_accommodations = Accommodation.joins(
"LEFT OUTER JOIN accommodations
 ON (reservations.hotel_id = accommodations.hotel.id
     AND reservations.accommodation_id = accommodations.id
     AND reservations.arrival <= ?
     AND reservations.departure >= ?)", departure, arrival)
.where("accommodations.hotel_id = ?", params[:id])
.where("reservations.id IS NULL")
.select("accommodations.*")

关键是连接条件reservations.arrival &lt;= departure AND reservations.departure &gt;= arrival。即仅在查询的到达和离开范围内加入预订到达或离开的住宿。 然后它在连接表中过滤出带有reservations.id IS NULL 的可用住宿。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多