【发布时间】:2018-10-06 04:27:38
【问题描述】:
我正在尝试在我的模型验证中使用 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 验证中适当地使用 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 的原始单行验证不起作用。如果有人仍然想用一个有效的答案来解释这一点,以加深我对过程和验证的理解,或者提供比我刚刚列出的更好的方法,我会接受你的答案。但这目前有效,所以我将继续使用它。谢谢。
【问题讨论】:
标签: ruby-on-rails validation ruby-on-rails-5 activemodel