在Rails验证中使用ActiveModel :: Dirty

时间:2018-04-25 15:56:41

标签: ruby-on-rails validation ruby-on-rails-5 activemodel

我正在尝试在我的模型验证中使用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的原始单行验证不起作用。如果有人仍然希望通过一个有效的解释来解释这一点,以加深我对过程和验证的理解,或提供比我刚刚列出的更好的方法,我会接受你的回答。但是现在这种方法有效,所以我打算用它。感谢。

0 个答案:

没有答案