【问题标题】:Search if vehicle is available between dates搜索日期之间是否有车辆可用
【发布时间】:2018-04-09 13:01:42
【问题描述】:

我创建了一个应用程序,用户可以在其中预订车辆(小巴) 我已经让应用程序在用户可以预订车辆但不能重复预订的情况下运行。我有一个简单的搜索工作,允许用户搜索品牌或型号。我希望扩展此搜索,以便用户可以搜索在用户想要预订的日期可用的所有车辆。我不太确定如何解决这个问题,有人可以帮忙!

我有一个 Vehicle 表、一个 User 表和一个 Reservation 表。

我的架构看起来像(我只包括了相关的表):

create_table "reservations", force: :cascade do |t|
  t.date "startDate"
  t.date "endDate"
  t.integer "noOfDays"
  t.integer "costs"
  t.integer "vehicle_id"
  t.integer "user_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["user_id"], name: "index_reservations_on_user_id"
  t.index ["vehicle_id"], name: "index_reservations_on_vehicle_id"
end
create_table "users", force: :cascade do |t|
  t.string "address"
  t.string "city"
  t.date "dateofbirth"
  t.string "email"
  t.string "fname"
  t.string "postcode"
  t.string "sname"
  t.string "user_type"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "password_digest"
  t.string "contact_no"
end
create_table "vehicles", force: :cascade do |t|
  t.string "description"
  t.integer "door"
  t.string "fuel"
  t.string "img"
  t.string "make"
  t.string "model"
  t.date "motEnd"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.date "motDue"
  t.date "motStart"
  t.integer "price"
  t.string "reg"
  t.integer "seats"
  t.string "transmission"
  t.date "year"
  t.decimal "engine"
end

我已经让重叠预订工作在这里与我使用的解决方案类似:Avoid double bookings for a minibus reservation system

我正在尝试扩大搜索范围,以便用户可以在索引页面上的两个日期之间搜索该时间段内的所有可用车辆。我只是不知道如何让它工作,所以系统会显示该日期的可用车辆。

我目前的简单搜索:

车辆控制器:

def vehicle_search
    vehicles = Vehicle.fuzzy_search(params[:search_string])
    @vehicles = Kaminari.paginate_array(vehicles.order :make).page(params[:page]).per(3)
    if @vehicles.empty?
        flash.now[:alert] = "No records found - displaying all records ..."
      @vehicles = Vehicle.order(:make).page(params[:page]).per(3)
    end

    render :action => "index"

结束

车辆.rb

def self.fuzzy_search(search_string)
    search_string ||= ""  
    make = search_string
    model = search_string
    price = search_string
    fuel = search_string
    transmission = search_string
    self.where("make LIKE ? OR model LIKE ? OR price LIKE ? OR fuel LIKE ? OR transmission LIKE ?", make, model, price, fuel, transmission)
end

搜索部分

<%= form_tag my_path, :method => 'post', :multipart => true do %>
  <!--vehicle details-->
  <%= text_field_tag :search_string, "", class: 'form-control custom2'  %>
  <%= submit_tag 'Search', class: "btn btn-default" %>
<% end %>

车辆/index.html.erb

<a>Make, Model, Fuel Type, Transmission: </a>
<%= render(:partial=>'/vehicle_search',:locals=> { :my_path => "/vehicles/vehicle_search" })%>

【问题讨论】:

  • 您很可能想要添加您正在使用的数据库。
  • 你的桌子怎么样?请展示它们的结构和一些示例数据。
  • 添加了更多细节

标签: ruby-on-rails ruby


【解决方案1】:

我将使用以下逻辑来确定时间重叠:

(StartA = StartB)

如果上面是true,则期间重叠。您可以在 Stack Overflow 问题中查看这一点:Determine Whether Two Date Ranges Overlap

因此,让我们在 Reservation 上创建两个范围。一种用于获取与一个时间点重叠的重叠预订,另一种用于获取与时间窗口重叠的重叠预订。

class Reservation < ApplicationRecord

  # code ...

  # assuming Reservation has start_time and end_time attributes
  # and you validate that start_time is always before end_time

  # time param can also be a date or datetime
  def self.overlap(time)
    # Reservation start_time is less than or equal to the given time
    # and reservation end_time is greater than or equal to the given 
    # time.
    where(arel_table[:start_time].lteq(time))
      .where(arel_table[:end_time].gteq(time))
  end

  def self.overlap_window(start_time, end_time)
    # Reservation start_time is less than or equal to the given
    # end_time and reservation end_time is greater than or equal 
    # to the given start_time.
    where(arel_table[:start_time].lteq(end_time))
      .where(arel_table[:end_time].gteq(start_time))
  end

  # code ...

end

现在您可以通过检查哪些车辆未被占用(例如某个时间窗口)来轻松获取车辆。

Vehicle.where.not(id: Reservation.select(:vehicle_id).overlap_window(Time.now, 4.hours.from_now))

注意: 开始时间必须始终在结束时间之前(对于预订和时间窗口),才能按照链接的日期重叠问题中的说明(主要在 cmets 中)工作开始。

【讨论】:

    猜你喜欢
    • 2011-09-02
    • 1970-01-01
    • 2012-12-11
    • 1970-01-01
    • 2017-12-15
    • 2019-07-28
    • 2012-09-30
    • 1970-01-01
    • 2015-07-01
    相关资源
    最近更新 更多