Open boardfish opened 3 years ago
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:
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. [...] }
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 thestate
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.