Rails - 按日期范围过滤 2 个模型
Rails - filter by date range with 2 models
我有两个型号:space和booking。 Space has_many bookings 和 Booking 有两个日期属性:check_in 和 check_out。
给定一个有效的日期范围,我想显示该范围内所有可用的 space
这是观点:
<%= form_tag spaces_path, method: :get do %>
<%= date_field_tag :query1,
params[:query1],
class: "form-control" %>
<%= date_field_tag :query2,
params[:query2],
class: "form-control" %>
<%= submit_tag "Search", class: "btn" %>
<% end %>
这是Space控制器:
(...)
def index
if params[:query1].present? && params[:query2].present?
query1 = DateTime.parse(params[:query1])
query2 = DateTime.parse(params[:query2])
search = query1..query2
bookings = Booking.all
# returns the bookings that overlaps with the search
overlapping_bookings = bookings.select do |booking|
check_in = booking[:check_in]
check_out = booking[:check_out]
period = check_in..check_out
search.overlaps?(booking.period)
end
# returns the spaces_id of the bookings that overlaps
overlapping_space_ids = overlapping_bookings.select do |overlapping_booking|
overlapping_booking[:space_id]
end
# remove the duplicates
overlapping_space_ids.uniq!
# remove the spaces with bookings that overlap with the search
@spaces = Space.all.reject do |space|
overlapping_space_ids.include? space[:id]
end
else
@spaces = Space.all
end
end
(...)
我假设我的问题的根本原因是我将 Active Record Query Object
视为一个哈希数组,不确定它是否正确。我对此做了一些研究,但我还没有找到任何详尽的答案。
使用 SQL 子查询(例如在 PostgreSQL 中)你会这样做:
sql = <<SQL
SELECT *
FROM spaces
WHERE id in (
SELECT space_id
FROM bookings
WHERE
(check_in, check_out) OVERLAPS (:from, :to)
)
SQL;
Booking.find_by_sql([sql, {from: query1, to: query2})
希望对您有所帮助:)
我会先向 Booking
模型添加一个范围:
# in app/models/booking.rb
scope :overlapping, ->(from, to) {
where(
"(check_in, check_out) OVERLAPS (?, ?)", from, to
)
}
然后将整个控制器方法更改为:
def index
@spaces = Space.all
if params[:query1].present? && params[:query2].present?
from = DateTime.parse(params[:query1])
to = DateTime.parse(params[:query2])
@space = @space.where.not(
id: Booking.select(:space_id).overlapping(from, to)
)
end
end
我有两个型号:space和booking。 Space has_many bookings 和 Booking 有两个日期属性:check_in 和 check_out。
给定一个有效的日期范围,我想显示该范围内所有可用的 space
这是观点:
<%= form_tag spaces_path, method: :get do %>
<%= date_field_tag :query1,
params[:query1],
class: "form-control" %>
<%= date_field_tag :query2,
params[:query2],
class: "form-control" %>
<%= submit_tag "Search", class: "btn" %>
<% end %>
这是Space控制器:
(...)
def index
if params[:query1].present? && params[:query2].present?
query1 = DateTime.parse(params[:query1])
query2 = DateTime.parse(params[:query2])
search = query1..query2
bookings = Booking.all
# returns the bookings that overlaps with the search
overlapping_bookings = bookings.select do |booking|
check_in = booking[:check_in]
check_out = booking[:check_out]
period = check_in..check_out
search.overlaps?(booking.period)
end
# returns the spaces_id of the bookings that overlaps
overlapping_space_ids = overlapping_bookings.select do |overlapping_booking|
overlapping_booking[:space_id]
end
# remove the duplicates
overlapping_space_ids.uniq!
# remove the spaces with bookings that overlap with the search
@spaces = Space.all.reject do |space|
overlapping_space_ids.include? space[:id]
end
else
@spaces = Space.all
end
end
(...)
我假设我的问题的根本原因是我将 Active Record Query Object
视为一个哈希数组,不确定它是否正确。我对此做了一些研究,但我还没有找到任何详尽的答案。
使用 SQL 子查询(例如在 PostgreSQL 中)你会这样做:
sql = <<SQL
SELECT *
FROM spaces
WHERE id in (
SELECT space_id
FROM bookings
WHERE
(check_in, check_out) OVERLAPS (:from, :to)
)
SQL;
Booking.find_by_sql([sql, {from: query1, to: query2})
希望对您有所帮助:)
我会先向 Booking
模型添加一个范围:
# in app/models/booking.rb
scope :overlapping, ->(from, to) {
where(
"(check_in, check_out) OVERLAPS (?, ?)", from, to
)
}
然后将整个控制器方法更改为:
def index
@spaces = Space.all
if params[:query1].present? && params[:query2].present?
from = DateTime.parse(params[:query1])
to = DateTime.parse(params[:query2])
@space = @space.where.not(
id: Booking.select(:space_id).overlapping(from, to)
)
end
end