繁体   English   中英

搜索多个表并将结果添加到数组

[英]Search multiple tables and add results to array

作为一个练习,我得到了一个包含三个表Booking,Room和Host的项目。 这些模型如下:

class Booking < ActiveRecord::Base
  belongs_to :room
end

class Room < ActiveRecord::Base
  belongs_to :host
  has_many :bookings
end

class Host < ActiveRecord::Base
  has_many :rooms
end

数据库模式如下所示:

ActiveRecord::Schema.define(version: 20150305133000) do

  create_table "bookings", force: true do |t|
    t.integer  "room_id",          null: false
    t.date     "start_date",       null: false
    t.date     "end_date",         null: false
    t.integer  "number_of_guests", null: false
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "hosts", force: true do |t|
    t.string   "name"
    t.string   "address"
    t.string   "picture_url"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "rooms", force: true do |t|
    t.integer  "host_id",    null: false
    t.integer  "capacity",   null: false
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

我需要实现一个搜索功能,该功能将返回所有主机,并在搜索表单指定的日期之间提供可用的房间。 要查找在所需日期可用的主机,我需要与“预订”表进行交叉引用。

我浏览了红宝石指南 ,也浏览了这个问题,但是我很难实现所阅读的内容。

在Rails控制台中,我一直在尝试各种查询以尝试获取所需的结果。

如果我让@bookings = Booking.includes(:room).all @hosts = []@hosts = []并且如果start_dateend_dateguests是他搜索返回的参数,则运行以下查询:

@bookings.each { |b| @hosts.push(b.room.host) if (b.start_date < start_date && b.end_date > end_date && (b.room.capacity - b.number_of_guests >= guests)) }

产生一个空的@hosts 然后我尝试了

 Booking.joins(:room).where("start_date < ? AND end_date > ? and capacity-number_of_guests >= ?", start_date, end_date, guests)

但这也返回了空的响应,因此我尝试着一步一步地找到所需日期的所有预订,过滤掉没有空间的房间,然后将所有房间的主机聚集在一起剩下。 我得到了:

@bookings = Booking.where("start_date = ? AND end_date >= ?",
  Date.parse(params[:start_date]),
  Date.parse(params[:end_date])).paginate(:page => params[:page], :per_page => 10)

@bookings.reject{ |booking| (booking.room.capacity - booking.number_of_guests) == 0 }

但是,这仍在返回空房间。 我已经在这里待了一天,所以如果有人能指出正确的方向来解决这个问题,我将不胜感激!

调试尝试

遵循denis-bu的建议,我已经更新了我的第一个查询以使其读取(暂时不留房间容量):

@bookings.each { |b| @hosts.push(b.room.host) if ((b.start_date > start_date &&
  b.start_date < end_date) || (b.end_date > start_date && b.end_date < end_date)) }

我已经在rails控制台中运行了它,然后当我尝试@hosts.count它返回0这意味着该查询未获取任何结果。 我希望看到一系列Host记录。

使用我的《 Where Exists》 gem和PostgreSQL:

Room.includes(:host).where_not_exists(:bookings,
 [
   "(?, ?) OVERLAPS (start_date, end_date)",
   params[:start_date],
   params[:end_date]
 ]
)

没有宝石:

# Using PostgreSQL OVERLAPS (http://www.postgresql.org/docs/9.0/static/functions-datetime.html)

overlaps = Booking.where(where("(?, ?) OVERLAPS (start_date, end_date)", start_date, end_date))

# With MySQL or SQLite you should check for boundaries manually

overlaps = Booking.where("? < end_date", start_date).where("? > start_date", end_date)

Room.includes(:host).where("NOT EXISTS (#{
  overlaps.where("bookings.room_id = rooms.id").to_sql
})")

关于您要实现的目标的详细信息还不够多,但是我猜测问题与您的条件有关: start_date < ? AND end_date > ? start_date < ? AND end_date > ? -检查查询日期是否在预订间隔内,而应该检查预订是否与查询日期重叠: ((b.start_date > START_DATE and b.start_date < END_DATE) OR (b.end_date > START_DATE and b.end_date < END)

但是,我想这不是您应该做的所有事情。 您还应该找到没有预订的房间以查询日期,然后合并这些集合。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM