这就是我最终想出的。如果有人有任何意见,请告诉我。我很想得到反馈。
validate :datetime_format_and_existence_is_valid
before_save :merge_and_set_datetime
# virtual attributes for date and time allow strings
# representing date and time respectively to be sent
# back to the model where they are merged and parsed
# into a datetime object in activerecord
def date
if (self.datetime) then self.datetime.strftime "%Y-%m-%d"
else @date ||= (Time.now + 2.days).strftime "%Y-%m-%d" #default
end
end
def date=(date_string)
@date = date_string.strip
end
def time
if(self.datetime) then self.datetime.strftime "%l:%M %p"
else @time ||= "7:00 PM" #default
end
end
def time=(time_string)
@time = time_string.strip
end
# if parsing of the merged date and time strings is
# unsuccessful, add an error to the queue and fail
# validation with a message
def datetime_format_and_existence_is_valid
errors.add(:date, 'must be in YYYY-MM-DD format') unless
(@date =~ /\d{4}-\d\d-\d\d/) # check the date's format
errors.add(:time, 'must be in HH:MM format') unless # check the time's format
(@time =~ /^((0?[1-9]|1[012])(:[0-5]\d){0,2}(\ [AaPp][Mm]))$|^(([01]\d|2[0-3])(:[0-5]\d){0,2})$/)
# build the complete date + time string and parse
@datetime_str = @date + " " + @time
errors.add(:datetime, "doesn't exist") if
((DateTime.parse(@datetime_str) rescue ArgumentError) == ArgumentError)
end
# callback method takes constituent strings for date and
# time, joins them and parses them into a datetime, then
# writes this datetime to the object
private
def merge_and_set_datetime
self.datetime = DateTime.parse(@datetime_str) if errors.empty?
end