【问题标题】:How to check if a date of a booking is overlapping rails hotel application如何检查预订日期是否与 Rails 酒店应用程序重叠
【发布时间】:2016-12-12 12:37:22
【问题描述】:

我正在为一家酒店使用 Ruby on Rails 制作一个 Web 应用程序。我看到了一些可能看起来和我一样的问题,但我找不到正确的解决方案。

用户可以创建预订并选择他们想要的房间以及到达和离开的日期。一切都按照我想要的方式进行,除了我的房间可以预订重叠日期。

架构

create_table "bookings", force: :cascade do |t|
  t.integer  "user"
  t.integer  "course"
  t.date     "arriving_date"
  t.date     "leaving_date"
  t.boolean  "breakfast"
  t.text     "remarks"
  t.datetime "created_at",    null: false
  t.datetime "updated_at",    null: false
  t.integer  "room_id"
  t.integer  "user_id"
  t.index ["room_id"], name: "index_bookings_on_room_id", using: :btree
  t.index ["user_id"], name: "index_bookings_on_user_id", using: :btree
end

create_table "rooms", force: :cascade do |t|
  t.string   "room_number"
  t.integer  "room_type_id"
  t.datetime "created_at",   null: false
  t.datetime "updated_at",   null: false
  t.index ["room_type_id"], name: "index_rooms_on_room_type_id", using: :btree
end

控制器

  def new
    @booking = Booking.new
  end

  def create
    @booking = Booking.new(booking_params)
    if @booking.save
      redirect_to @booking
    else
      flash[:notice] = "Something went wrong"
      render 'index'
    end
  end

预订模式

class Booking < ApplicationRecord
  belongs_to :room
  belongs_to :user
end

我想要什么

当用户尝试创建预订时,他们不应该选择在他们想在酒店睡觉的日子已经预订的特定房间。

【问题讨论】:

  • 想要到目前为止吗?显示您的验证方法
  • @Fallenhero 我明白你为什么这么问,但问题是我完全不知道如何制作这样的东西..

标签: ruby-on-rails ruby


【解决方案1】:

在最粗略的伪代码中,我会用实例方法扩展 Room

# room.rb
def is_available? time_range
  bookings.present?(:arrival < time_range.end AND :depature > timerange.start)
end

在控制器的创建操作中调用它,就像在自己的答案中一样。

您肯定希望在不遍历所有预订的情况下这样做!

【讨论】:

  • 谢谢你的回答,我试试看!
  • @StijnWesterhof 如果可行,请随意编辑并提供真实代码(可能编辑您自己的答案)。
【解决方案2】:

我已经尝试了给定的答案,但我还不能让它起作用。所以我制定了自己的解决方案,但我对此并不满意,因为“胖模型,瘦控制器”的事情。

这对我有用:

def create
  @booking = Booking.new(booking_params)

  @date_start = @booking.arriving_date.strftime("%Y-%m-%d")
  @date_end = @booking.leaving_date.strftime("%Y-%m-%d")

  found = false
  @all_bookings = Booking.all
  @all_bookings.each do |booking|
    arival_date = booking.arriving_date.strftime("%Y-%m-%d")
    leave_date = booking.leaving_date.strftime("%Y-%m-%d")
    if @date_start.between?(arival_date, leave_date) || @date_end.between?(arival_date, leave_date)
      if booking.room_id == @booking.room_id
        found = true
      end
    end
  end

  if found == true
    redirect_to new_booking_path, notice: "This room is already booked in the period you want to book it"
  else
    @booking.save!
    redirect_to @booking
  end
end

我仍然对“正确”答案感兴趣:)

【讨论】:

  • 不要重复您的预订。您需要找到ActiveRecord 或 SQL 解决方案。如果必须,不要使用find,而是使用find_each(如果订购不重要)。此外,在您找到预订时提前停止(您的代码将检查所有预订,即使第一个预订重叠!)。
【解决方案3】:

好的。您将需要类似的东西(在您的预订模型中):

validate(:validate_overlapping)

def validate_overlapping
  self.errors[:date] = "Overlapping booking" if Booking.where(#check_your_dates#).first
end

【讨论】:

    【解决方案4】:

    将以下内容添加到您的预订模型中,

    before_create: check_date_availability
    
    def self.check_date_availability(booking_params)
      bookings = Booking.where('arrival_date < ? OR leaving_date > ?', self.arrival_date, self.leaving_date)
      return bookings.empty?
    end
    

    请更改查询中的条件。 AND 或 OR 根据您的要求。

    【讨论】:

    • Shabihi,你的函数不能只返回 bookings.empty 吗?不需要 if/else/end。
    • 是的,这也很好。感谢@ZaurAmikishiyev 的捕获。更新了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    相关资源
    最近更新 更多