我使用的日历 gem 使用
start_time
表示日期 (YYYY-MM-DD)。
出于示例目的,我有
Meeting
,它具有 start_time
字符串和 postponed
布尔属性。
@meeting.start_time
必须至少是未来一天(后天),但如果 start_time
,则无法设置新的 @meeting.postponed
(会议日期),仅当 @meeting.postponed == false
此外,如果
@meeting.postponed
,则无法在不设置新的@meeting.start_time
(即至少未来一天)的情况下取消推迟。
我想要验证,因此在更新会议时(如果
@meeting
之前被推迟),我想取消选择 @meeting.postponed
复选框并在表单中提交新的 @meeting.start_date
,并让它在同一提交中通过。
如果在控制器中,类似:
@meeting.attributes = meeting_params
if @meeting.start_time != "" && @meeting.start_time != nil
if @meeting.start_time_changed?
if @meeting.posteponed
@error = "Can't change the Meeting Date if the Meeting is still postponed."
else
if @meeting.start_time.to_date <= Date.today
@error = "Meeting must be at least one day in the future."
end
end
else
if @meeting.postponed_changed? && @meeting.postponed == false
@error = "You can't un postpone the Meeting without setting a new Meeting Date."
end
end
else
@error = "Meeting Date cannot be blank."
end
如何通过验证来做到这一点?
不要将模型的所有业务逻辑集中到一个疯狂的条件分支树中,而是对每个方面使用单独的验证。我认为你实际上把它复杂化了。
您可以使用
on:
选项控制何时触发验证,编写自定义验证器就像创建方法并使用 validate :method_name
一样简单。如果您想创建更复杂的验证器,请创建一个 validator 类。
class Meeting
validates :start_time, presence: true
validates :start_time_must_be_in_future,
if: :start_time?, # prevents a nil error
unless: :postponed?,
on: :create
validates :start_time_cannot_change_when_postponed,
if: :postponed?
on: :update
private
def start_time?
!start_time.nil?
end
def start_time_must_be_in_future
errors.add(
:start_time,
"Meeting must be at least one day in the future."
) if start_time.to_date <= Date.today
end
def start_time_cannot_change_when_postponed
errors.add(
:start_time,
"Can't change the Meeting Date if the Meeting is still postponed."
) if will_save_change_to_start_date?
end
end
有诸如 validates_timeiness 之类的宝石可以使时间验证变得不那么繁重。