這兩個點是什么意思..在導軌中
有這樣的功能:
def period
start_date..end_date
end
它是什么?這會生成一個陣列嗎?我看到這個在這個類中使用
class Booking < ApplicationRecord
# ... some code is skipped here for simplicity's sake
validate :validate_other_booking_overlap
def period
start_date..end_date
end
private
def validate_other_booking_overlap
other_bookings = Booking.all
is_overlapping = other_bookings.any? from |other_booking|
period.overlaps?(other_booking.period)
end
errors.add(:overlaps_with_other) if is_overlapping
end
end
uj5u.com熱心網友回復:
Range這是ruby 中包容性有限的字面語法。
Range 表示一個區間——一組具有開始和結束的值...當用作迭代器時,范圍回傳序列中的每個值。
范圍可以表示為包含的兩個點 ( ..) 或排除的三個點 ( ...)。獨占范圍不包括最后一個元素。
在 2.6 之前,所有范圍都是有限的(在語法上需要一個開始和一個結束;雖然結束可能是Float::INFINITY[與-Float::INFINITY開始相反 ],所以從技術上講,并非所有范圍都是“有限的”)。
在 2.6 中,“無限范圍”是使用語法實作的x..。
從 2.7 開始,范圍可以使用語法“無開始”..x
根據檔案,beginless 和無限范圍都是“半無限”的,可以表示為包含或排除。(老實說,我不確定什么是專有的無限范圍;盡管語法具有創造性的用途 [見下文])
作為旁注:(TL;DR)
從性能的角度來看,遍歷每一個Booking都是一個壞主意。
一個更好的主意是使用以下方法將其卸載到資料庫:
def validate_other_booking_overlap
overlaps_bookings = Booking
.where(start_date: period)
.or(Booking.where(end_date: period))
.or(
Booking.where(
Booking.arel_table[:start_date].gt(start_date)
.and(Booking.arel_table[:end_date].lt(end_date))))
.where.not(id: id)
.exists?
errors.add(:overlaps_with_other) if overlaps_bookings
end
Rails (Arel) 將 WHERE 條件中的有限范圍轉換為 SQL BETWEEN 子句,因此該查詢條件為:
WHERE
((bookings.start_date BETWEEN '####-##-##' AND '####-##-##'
OR bookings.end_date BETWEEN '####-##-##' AND '####-##-##')
OR (
bookings.start_date > '####-##-##'
AND bookings.end_date < '####-##-##'
))
AND bookings.id != # -- IS NOT NULL on create
在較新版本的 rails (>=6.0.3 和 ruby?? >= 2.7) 中:
Booking.arel_table[:start_date].gt(start_date)
.and(Booking.arel_table[:end_date].lt(end_date))
可以用這個代替
Booking.where(start_date: start_date..., end_date:...end_date))
因為現在 Rails (Arel) 對 Ranges 的處理方式如下:
x..yx AND y 之間的屬性(例如屬性 >= x AND 屬性 <= y)x...y屬性 >= x AND 屬性 < yx..屬性 >= xx...屬性 > x..x屬性 <= x...x屬性 < x
...現在我相信我們已經完成了一個完整的回圈。
更新
由于@max的評論,您可以使用該OVERLAPS功能(資料庫支持它)如下
def validate_other_booking_overlap
left = Arel::Nodes::Grouping.new(
Booking.arel_table[:start_date],
Booking.arel_table[:end_date])
right = Arel::Nodes::Grouping.new(
Arel::Nodes::UnaryOperation.new(
'DATE',
Arel::Nodes.build_quoted(start_date - 1)),
Arel::Nodes::UnaryOperation.new(
'DATE',
Arel::Nodes.build_quoted(end_date 1)))
condition = Arel::Nodes::InfixOperation.new('OVERLAPS', left, right)
errors.add(:overlaps_with_other) if Booking.where.not(id: id).where(condition).exists?
end
這是未經測驗并根據記憶和理解寫在手機上的(不能保證結果)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/419423.html
標籤:
上一篇:Bootstrap和Rails的collection_check_boxes
下一篇:洗掉列并用自定義方法替換它
