You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It's based on an attribute that's not persisted to the database - a transient attribute. I define this with an attr_accessor and set its initial value in an after_initialize hook. The initial value is figured out from the current state of the record.
This is a useful approach because the state machine can be changed without a significant negative impact on existing records - if a new state were introduced between one and two, for example, two would still be stored in the database and would leave all two records in that state, whereas if it's dynamically figured out, they'd just move back to one with all data intact. It's just as useful for validating records at different stages while being a little more flexible where you need it.
There are a couple of quirks with this approach at the moment, though:
The validator I've added up there doesn't run. I'm following the advice here to set the validation on both the one and two states. The fact that the validator doesn't run then means I need to use the commented part to protect that transition.
I did some experimenting myself and the state block does get called, but the validate block does not.
initial: doesn't work. I tried setting it to a lambda and a symbol, and I also tried playing with initialize_state_machine(force: true). The fix as mentioned is to set its initial value in an after_initialize hook as you would any other transient attribute, but it'd be better to have it within the state machine declaration.
The text was updated successfully, but these errors were encountered:
I've since changed approaches - I'm now using a dynamic state machine as per the docs. Thus far, I think I'd recommend that, but I've got the following observations:
The state machine is on the Machine class rather than the object that gets passed in to Machine#new. You'll need to allow the machine to recognize the parent object if you want to use that in conditional transitions. Aim for something like if: ->(machine) { machine.parent. [...] }
You'll also need to set the initial state based on the parent object.
Tangentially related, but with transient attributes, use the ActiveRecord Attributes API.
I have a state machine on a class that inherits from
ActiveRecord::Base
that's something like this:It's based on an attribute that's not persisted to the database - a transient attribute. I define this with an
attr_accessor
and set its initial value in anafter_initialize
hook. The initial value is figured out from the current state of the record.This is a useful approach because the state machine can be changed without a significant negative impact on existing records - if a new state were introduced between
one
andtwo
, for example,two
would still be stored in the database and would leave alltwo
records in that state, whereas if it's dynamically figured out, they'd just move back toone
with all data intact. It's just as useful for validating records at different stages while being a little more flexible where you need it.There are a couple of quirks with this approach at the moment, though:
one
andtwo
states. The fact that the validator doesn't run then means I need to use the commented part to protect that transition.I did some experimenting myself and the
state
block does get called, but thevalidate
block does not.initial:
doesn't work. I tried setting it to a lambda and a symbol, and I also tried playing withinitialize_state_machine(force: true)
. The fix as mentioned is to set its initial value in anafter_initialize
hook as you would any other transient attribute, but it'd be better to have it within the state machine declaration.The text was updated successfully, but these errors were encountered: