时间范围方法在 Rails 4/Ruby 2 应用程序中不起作用
Time range method not working in Rails 4/Ruby 2 app
我需要帮助解决 Rails 4/Ruby 2.0 应用程序中的时间范围问题。在我的约会模型中,我想防止用户在营业时间以外进行约会,即 6:30 a.m。到 9:00 p.m。该模型在名为 appointment_date 的列中跟踪约会时间,该列属于 DateTime 数据类型。
我尝试通过将以下方法放在 app/validators 目录中来解决问题:
class DuringBusinessHoursValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value.present? && during_business_hours(value)
record.errors[attribute] << 'must be during business hours (6:30 am - 9:00 pm)'
end
end
def during_business_hours(time)
# from
Range.new(
Time.local(time.year, time.month, time.day, 6, 30),
Time.local(time.year, time.month, time.day, 21, 0)) === time
end
end
我将以下代码放入我的约会模型中:
validates :appointment_date, during_business_hours: true
但是,Rails 抛出以下错误:
TypeError in AppointmentsController#update
can't iterate from Time
当我删除方法中的一个 === 符号时,Rails 不会生成错误,但代码无法正确运行。使用 == 时,所有约会都会受到限制,即使是那些发生在 6:30 am 和 9:00 pm 之间的约会。
我阅读了另一个 Whosebug post,其中有人报告了使用 Ruby 2.0 执行上述方法时出现的问题。这个人说他们通过 "converting the range endpoints with .to_i, and then comparing with t.to_i." 解决了这个问题,所以,我将第二种方法中的代码更改如下:
def during_business_hours(t)
t = Time.now
Range.new(
Time.local(t.year, t.month, t.day, 6, 30).to_i,
Time.local(t.year, t.month, t.day, 21).to_i
) === t.to_i
end
end
但是,该更改不起作用。它会产生相反的问题:Rails 允许所有约会,无论时间如何。
对于如何进一步排除故障并解决问题有什么想法或建议吗?如果有任何帮助,我将不胜感激!
我会利用 DateTime 对象支持比较这一事实。例如
Time.local(2014, 12, 31, 6, 30) > Time.local(2015, 1, 1, 6, 30)
=> false
因此您可以重写方法 during_business_hours
:
# Check if time `t` is between 6:30 and 21:00 of `t`'s day, a.k.a. in between business hours.
# If that's the case, return true, otherwise false.
def during_business_hours(t)
if t < Time.local(t.year, t.month, t.day, 6, 30) ||
t > Time.local(t.year, t.month, t.day, 21)
return false
else
return true
end
end
就个人而言,您当前的该方法的代码很难阅读,新版本更加清晰。
...顺便说一句,我会将其设为 private
方法。
def validate_each [snip]
private
def during_business_hours(t)
[snip]
我需要帮助解决 Rails 4/Ruby 2.0 应用程序中的时间范围问题。在我的约会模型中,我想防止用户在营业时间以外进行约会,即 6:30 a.m。到 9:00 p.m。该模型在名为 appointment_date 的列中跟踪约会时间,该列属于 DateTime 数据类型。
我尝试通过将以下方法放在 app/validators 目录中来解决问题:
class DuringBusinessHoursValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value.present? && during_business_hours(value)
record.errors[attribute] << 'must be during business hours (6:30 am - 9:00 pm)'
end
end
def during_business_hours(time)
# from
Range.new(
Time.local(time.year, time.month, time.day, 6, 30),
Time.local(time.year, time.month, time.day, 21, 0)) === time
end
end
我将以下代码放入我的约会模型中:
validates :appointment_date, during_business_hours: true
但是,Rails 抛出以下错误:
TypeError in AppointmentsController#update
can't iterate from Time
当我删除方法中的一个 === 符号时,Rails 不会生成错误,但代码无法正确运行。使用 == 时,所有约会都会受到限制,即使是那些发生在 6:30 am 和 9:00 pm 之间的约会。
我阅读了另一个 Whosebug post,其中有人报告了使用 Ruby 2.0 执行上述方法时出现的问题。这个人说他们通过 "converting the range endpoints with .to_i, and then comparing with t.to_i." 解决了这个问题,所以,我将第二种方法中的代码更改如下:
def during_business_hours(t)
t = Time.now
Range.new(
Time.local(t.year, t.month, t.day, 6, 30).to_i,
Time.local(t.year, t.month, t.day, 21).to_i
) === t.to_i
end
end
但是,该更改不起作用。它会产生相反的问题:Rails 允许所有约会,无论时间如何。
对于如何进一步排除故障并解决问题有什么想法或建议吗?如果有任何帮助,我将不胜感激!
我会利用 DateTime 对象支持比较这一事实。例如
Time.local(2014, 12, 31, 6, 30) > Time.local(2015, 1, 1, 6, 30)
=> false
因此您可以重写方法 during_business_hours
:
# Check if time `t` is between 6:30 and 21:00 of `t`'s day, a.k.a. in between business hours.
# If that's the case, return true, otherwise false.
def during_business_hours(t)
if t < Time.local(t.year, t.month, t.day, 6, 30) ||
t > Time.local(t.year, t.month, t.day, 21)
return false
else
return true
end
end
就个人而言,您当前的该方法的代码很难阅读,新版本更加清晰。
...顺便说一句,我会将其设为 private
方法。
def validate_each [snip]
private
def during_business_hours(t)
[snip]