[英]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.