我的模型中有一个自定义验证:
class Appointment < ActiveRecord::Base
#VIRTUAL ATTRIBUTES
attr_accessor :start_date, :start_time, :duration
#RELATIONSHIPS
belongs_to :task
#VALIDATIONS
before_validation :convert_to_datetime
before_validation :dur
validates :duration, presence: true
validate :is_date_nil
validate :time_collision_validation, if: :is_appointments_not_empty
validate :check_time
after_save :save_start_date
def is_appointments_not_empty
Appointment.all.present?
end
def check_time
start_at = Time.parse("#{@start_date} #{@start_time}")
if start_at < Time.now
errors.add(:start_date, "Cannot input past times")
end
end
def convert_to_datetime
unless @start_date.blank? && @start_time.blank?
self.start_at = Time.parse("#{@start_date} #{@start_time}")
end
end
def dur
if @start_date.present? && @start_time.present? && @duration.present?
self.end_at = Time.parse("#{@start_date} #{@start_time}") + (@duration.to_f*60*60)
end
end
def time_collision_validation
appointments = Appointment.all
if @start_date.present? && @start_time.present? && duration == 0.to_s
start_at = Time.parse("#{@start_date} #{@start_time}")
end_at = Time.parse("#{@start_date} #{@start_time}") + (@duration.to_f*60*60)
appointments.each do |a|
if start_at <= a.end_at - (2*60*60) && start_at >= a.start_at - (1*60*60)
errors.add(:start_time)
errors.add(:start_date, "An appointment already
exists at #{a.start_at.strftime("%I:%M%p")} of #{a.start_at.strftime("%d/%m/%Y")}
to #{a.end_at.strftime("%I:%M%p")} of #{a.end_at.strftime("%d/%m/%Y")}.
Please select a different date or time.")
break
end
end
elsif @start_date.present? && @start_time.present? && duration.present?
start_at = Time.parse("#{@start_date} #{@start_time}")
end_at = Time.parse("#{@start_date} #{@start_time}") + (@duration.to_f*60*60)
appointments.each do |a|
if start_at <= a.end_at - (2*60*60) && a.start_at <= end_at
errors.add(:start_time)
errors.add(:start_date, "An appointment already
exists at #{a.start_at.strftime("%I:%M%p")} of #{a.start_at.strftime("%d/%m/%Y")}
to #{a.end_at.strftime("%I:%M%p")} of #{a.end_at.strftime("%d/%m/%Y")}.
Please select a different date or time.")
break
end
end
end
end
def is_date_nil
if @start_date.blank? && @start_time.blank?
errors.add(:start_date, "Start date can't be blank")
errors.add(:start_time, "Start time can't be blank")
end
if @start_date.blank? && @start_time.present?
errors.add(:start_date, "Start date can't be blank")
end
if @start_time.blank? && @start_date.present?
errors.add(:start_time, "Start time can't be blank")
end
end
def start_date=(date)
@start_date = Date.strptime(date, "%d/%m/%Y") if date.present?
end
# def save_start_date
# @start_date = Date.strptime(@start_date, "%d/%m/%Y") if @start_date.present?
# end
# def save_start_date
# @start_date = Date.parse(@start_date).strftime("%d/%m/%Y")if @start_date.present?
# end
def start_time=(time)
@start_time = Time.parse(time).strftime("%H:%M:%S") if time.present?
end
def duration=(duration)
@duration = duration if duration.present?
end
# def start_date
# @start_date.strftime("%d/%m/%Y") if start_at.present? # || start_at.strftime("%d/%m/%Y") if start_at.present?
# end
def start_date
unless @start_date.blank?
@start_date.strftime("%d/%m/%Y")
end
# start_at.strftime("%d/%m/%Y") if start_at.present?
end
def start_time
@start_time || start_at.strftime("%I:%M%p") if start_at.present?
end
# def duration
# @duration || 9
# end
end
执行time_collision_validation后,值字段为空白,我不想要,因为我关注的是UX。即:start_date和start_time字段为空。
当我在HTML源代码中检查输入中的value属性时,该值包含日期字符串。我想知道为什么它没有在现场展示。
有人可以帮我解释一下这是怎么回事吗? &GT;。&LT;
答案 0 :(得分:0)
validate :time_collision_validation
def time_collision_validation
appointments = Appointment.all
if self.start_date.present? && self.start_time.present? && duration.present?
start_at = Time.parse("#{self.start_date} #{self.start_time}")
end_at = Time.parse("#{self.start_date} #{self.start_time}") + (self.duration.to_f.hours)
appointments.each do |appointment|
if duration == 0.to_s
duration_ok = start_at >= appointment.start_at - (1.hours)
else
duration_ok = appointment.start_at <= end_at
end
if start_at <= appointment.end_at - (2.hours) && duration_ok
errors.add(:start_time)
errors.add(:start_date, "An appointment already
exists at #{appointment.start_at.strftime("%I:%M%p")} of #{appointment.start_at.strftime("%d/%m/%Y")}
to #{appointment.end_at.strftime("%I:%M%p")} of #{appointment.end_at.strftime("%d/%m/%Y")}.
Please select a different date or time.")
break
end
end
end
end
注意:
duration
和self.duration
。为了便于阅读,我总是使用self.duration
而不是duration
或self.duration
,因为它使读者清楚您正在谈论当前对象的方法/字段而不是局部变量。我已将当前对象的引用方法/字段的所有实例更改为self.methodname
2*60*60
就像说2.hours
,后者更具可读性。