我正在尝试在我的模型验证中使用Rails ActiveModel :: Dirty来要求存在某些字段,具体取决于我的记录的status
是什么或将是什么。
当前验证
validates :pause_reason, presence: true, if: Proc.new { |o| o.status_will_change! == "Paused" }
validates :unpause_reason, presence: true, if: Proc.new { |o| o.status_was == "Paused" }
因此,pause_reason
验证似乎工作正常,就像我将状态更改为Paused
并将pause_reason
留空一样时,我得到相应的错误“暂停原因不能为空”如果我填写所述字段,我就不会收到错误。
但是,当我尝试保存相同的更改时,unpause_reason
验证还会显示错误“取消暂停原因不能为空”。我试图通过以下结果逐步完成rails控制台中的步骤:
irb(main):026:0> o.status
=> "Open"
irb(main):027:0> o.status = "Paused"
=> "Paused"
irb(main):028:0> o.status_will_change!
=> nil ## should be "Paused" I think
irb(main):029:0> o.status_was
=> "Open"
irb(main):030:0> o.status_was == "Paused"
=> false
irb(main):031:0> o.pause_reason
=> nil
irb(main):032:0> o.valid?
=> true ## should be false
所以我想我对验证过程中发生的事情有点困惑,这会导致pause_reason
验证(貌似)按预期工作,但是当{}}验证时失败unpause_reason
验证失败控制台清楚地显示status_was
等于"Open"
。
如果有人可以帮助我理解如何在Rails Validations中正确使用ActiveModel :: Dirty,那将非常感激。
更新
经过更多研究,我决定将我的“状态验证”合并到一个在update
上验证的方法,如下所示:
validates :status_change_validations, on: :update
def status_change_validations
if status == "Paused" && pause_reason.blank?
errors.add(:pause_reason, 'required when pausing an order.')
elsif status != "Paused" && status_was == "Paused" && unpause_reason.blank?
errors.add(:unpause_reason, 'required when resuming an order.')
elsif status == "Canceled" && cancellation_reason.blank?
errors.add(:cancellation_reason, 'required when canceling an order.')
elsif status != "Canceled" && status_was == "Canceled" && reopen_reason.blank?
errors.add(:reopen_reason, 'required when reopening an order.')
elsif status == "Reactivate" && reactivation_reason.blank?
errors.add(:reactivation_reason, 'required when reactivating an order.')
end
end
这似乎完全符合我的意图,但是,我仍然不确定为什么使用Procs
的原始单行验证不起作用。如果有人仍然希望通过一个有效的解释来解释这一点,以加深我对过程和验证的理解,或提供比我刚刚列出的更好的方法,我会接受你的回答。但是现在这种方法有效,所以我打算用它。感谢。