搜索日期之间是否有车辆

时间:2018-04-09 13:01:43

标签: ruby-on-rails ruby

我已经创建了一个应用程序,用户可以预订车辆(小巴)我已经让应用程序在用户可以预订车辆的地方工作,但车辆不能预订。我有一个简单的搜索工作,允许用户搜索品牌或型号。我正在寻求扩展此搜索,以便用户可以搜索所有可用于用户想要预订的日期的车辆。我不太确定怎么接近这个可以请有人帮忙!

我有一张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"

vehicle.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" })%>

1 个答案:

答案 0 :(得分:1)

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

(StartA&lt; = EndB)和(EndA&gt; = StartB)

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

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

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))

注意:开始时间必须始终在结束时间之前(对于预订和时间窗口),这可以按照在日期重叠问题中解释的(主要在注释中)解释一开始。