[英]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_date
, end_date
和guests
是他搜索返回的参数,则运行以下查询:
@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.