In Ruby, how would I run a validation that says that a model attribute can only be X if it used to be Y? The example would be an attribute status
that takes either in-progress
or complete
. I'd want to say when user marks the object status, it can always be marked in-progress
, but it can only be marked complete
if it was first marked 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
Please consider use ActiveModel::Dirty
It provides methods to track these changes.
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
Also it's not need to use self.
keyword here.
You can use the change tracking provided by rails for this. In particular status_was
returns the previous value of status. You can also use status_changed
to know where the status has been changed (or else you would prevent other changes to complete models)
Personally I don't massively like the idea of validations that depend on other things than the current set of attributes. You may find that using a state machine (for example aasm) is a better way of enforcing this sort of behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With