如何正确验证虚拟属性、日期字段

How to properly validate virtual attributes, date field

除验证外一切正常。我想正确验证这一点:我有 2 个字段映射到模型的一个属性中。对于这种情况,我有 start_at 和 end_at,每个都有 2 个字段。我也想处理 nil 输入(ArgumentError)。

这是我的代码:

class Appointment < ActiveRecord::Base
    #VIRTUAL ATTRIBUTES
    attr_accessor :start_date, :start_time, :end_date, :end_time

    #RELATIONSHIPS
    belongs_to :task

    #VALIDATIONS

    before_save :convert_to_datetime

    def start_date
        start_at.strftime("%d/%m/%Y") if start_at.present?

    end 

    def start_time
        start_at.strftime("%I:%M%p") if start_at.present?
    end

    def start_date=(date)
  # Change back to datetime friendly format
  @start_date =  Date.strptime(date, "%m/%d/%Y")
end

def start_time=(time)
  # Change back to datetime friendly format
  @start_time = Time.parse(time).strftime("%H:%M:%S")

end

def end_date
    end_at.strftime("%d/%m/%Y") if end_at.present?
end 

def end_time
    end_at.strftime("%I:%M%p") if end_at.present?
end

def end_date=(date)
  # Change back to datetime friendly format
  @end_date = Date.strptime(date, "%m/%d/%Y")
end

def end_time=(time)
  # Change back to datetime friendly format
  @end_time = Time.parse(time).strftime("%H:%M:%S")
end

def convert_to_datetime
    self.start_at = DateTime.parse("#{@start_date} #{@start_time}")
    self.end_at = DateTime.parse("#{@end_date} #{@end_time}")
end

end

强参数:

params.require(:task).permit(:category_id, :subcategory_id, :title, :description, :pay_offer, :pay_type, :county_id, :area_id, appointments_attributes: [:id, :start_date, :start_time, :end_date, :end_time])

请帮忙...

您可以使用 before_validation 回调而不是 before_save。 在这种情况下,您可以对 start_at 和 end_at 进行验证,它们是普通属性。你可能想要 presence validator.

验证看起来像这样:

validates :start_at, presence: true
validates :end_at, presence: true

更新:

您还必须确保不要尝试解析空白字符串。

def start_date=(date)
  # Change back to datetime friendly format
  unless date.blank?
    @start_date =  Date.strptime(date, "%m/%d/%Y")
  end
end

def start_time=(time)
  # Change back to datetime friendly format
  unless time.blank?
    @start_time = Time.parse(time).strftime("%H:%M:%S")
  end
end

def end_date=(date)
  # Change back to datetime friendly format
  unless date.blank?
    @end_date = Date.strptime(date, "%m/%d/%Y")
  end
end

def end_time=(time)
  # Change back to datetime friendly format
  unless time.blank?
    @end_time = Time.parse(time).strftime("%H:%M:%S")
  end
end

更新 2:

 unless @start_date.blank? && @start_time.blank? && @end_date.blank? && @end_time.blank?
        self.start_at = DateTime.parse("#{@start_date} #{@start_time}")

        self.end_at = DateTime.parse("#{@end_date} #{@end_time}")
    end