ActiveRecord验证中属性的旧值和新值

时间:2016-04-29 05:01:22

标签: ruby-on-rails ruby activerecord

在Ruby中,我如何运行验证,如果曾经是Y,模型属性只能是X?该示例是属性status,可以使用in-progresscomplete。我想说当用户标记对象状态时,可以始终将其标记为in-progress,但只有在complete被标记为in-progress时才能标记为validate :status_change def status_change unless self.status == "complete" && #here i want to say self.status used to be "in progress" errors[:base] << "Can only mark object complete after it was first marked in progress" end end

Protection level

5 个答案:

答案 0 :(得分:3)

您可以使用rails提供的change tracking。特别是status_was返回先前的状态值。您还可以使用status_changed来了解状态的更改位置(或者您可以阻止其他更改来完成模型)

我个人并不喜欢依赖于除当前属性集之外的其他事物的验证的想法。您可能会发现使用状态机(例如aasm)是执行此类行为的更好方法。

答案 1 :(得分:2)

请考虑使用ActiveModel::Dirty

它提供了跟踪这些变化的方法。

before_update :status_change

def status_change
  unless status == "complete" && status_was == "in-progress" 
    errors[:base] << "Can only mark object complete after it was first marked in progress"
  end
end

此处也不需要使用self.关键字。

答案 2 :(得分:0)

我相信你正在尝试为模型实现状态。 我建议您使用AASM

设置简单,您可以避免所有这些回调和验证。

答案 3 :(得分:0)

您希望仅在状态before_update :status_change def status_change errors[:base] << "Error Message" unless status_was == "in-progress" end 首次标记为{{1}}时标记 你可以尝试这个解决方案

{{1}}

由于

答案 4 :(得分:0)

validates :status, inclusion: { in: %w(complete) }, if: Proc.new { |status| status.changed? && status_was == 'in-progress' }

这样的事情可以帮助解决你的问题。但是我认为你正在尝试重塑状态机的概念,如果是这种情况,那么我会投票给其他人建议使用AASM gem