我的模型中有这个方法:
def date_ranges
reservations = Reservation.where(["transport_id =?", transport_id])
reservations = reservations.where(['id <> ?', id]) if !id.nil?
reservations.map { |e| e.reservation_start..e.reservation_end }
end
它运行得很好(感谢StackOverflow的一些帮助)。
我的reservation_start
和reservation_end
列属于date
类型。这是我的迁移:
class CreateReservations < ActiveRecord::Migration
def change
create_table :reservations do |t|
t.references :user, index: true
t.references :transport, index: true
t.date :reservation_start
t.date :reservation_end
t.timestamps
end
end
end
如果我在从date
列类型迁移到datetime
类型后尝试运行此方法,则会收到错误消息:
can't iterate from ActiveSupport::TimeWithZone
即使我将方法中的代码更改为:
,它仍然无法正常工作reservations.map do |e|
e.reservation_start.to_datetime..e.reservation_end.to_datetime
end
答案 0 :(得分:1)
不幸的是,如果要迭代DateTime范围,则范围应该具有至少1天的粒度。因此,似乎错误出现在您使用#date_ranges
的地方,而不是在方法本身。
由于您正在使用ActiveSupport::TimeWithZone
(这是使用datetime
SQL类型时获得的对象类型),您可以获得比日期更精确的内容 - 您还有时间
所以取决于你如何使用这个方法。
您有两种方法可以解决此问题:
将代码更改为以下内容:
reservations.map do |e|
e.reservation_start.to_date..e.reservation_end.to_date
end
这样你就会失去时间精确度,只能回到日期。
更改您使用#date_ranges
方法的方式。可能最好的方法是让它返回[begin_date, end_date]
的数组。
def date_ranges
Reservation.where(transport_id: transport_id).pluck(:reservation_start, :reservation_end)
end
根据您使用范围的方式,您可以解决这个问题:
如果您要检查特定时间是否在任何给定的日期范围内,您可以执行以下操作:
date_ranges.any? { |date_range| date_range.cover?(my_time) }
如果您要显示日期:
date_ranges.each do |date_range|
# display the date range
end