Return to previous saved state with state_machine & state_machine_audit_trail
I have a Rails 3.1 application that uses the state_machine gem (https://github.com/pluginaweek/state_machine) to track a model's states. and the state_machine-audit_trail gem (https://github.com/wvanbergen/state_machine-audit_trail) to save the state changes.
#State Machine states for Work Orders
state_machine :initial => :created do
after_transition :on=>:validate, :do=>:create_report
store_audit_trail
event :validate do
transition :created => :validated
end
event :reject do
transition :cre开发者_StackOverflowated => :rejected
end
end
There is one particular state 'rejected' that is temporary, and I'm looking for a way to trigger an event to return the model to the previous state as saved in the WorkOrderStateTransition model (provided by the audit gem).
I created a method 'previous_state' that finds the last state transition, and when the method is called via console it does return the previous state name.
The problem is I'm unable to call that method within the state_machine transition to use it as the destination state on a restore. To illustrate, something like this does not work:
event :restore do
transition :rejected => lambda {|wo| wo.previous_state}
end
What I get stored as a state is a Proc.
I would have thought this would be a pretty common use case (returning to a previously saved state) but I have found very little info while searching. The only post that is relevant is Using pluginaweek's state_machine, can I reference the activerecord object during an event? But this does not use the workflow history provided by the audit gem , and also returns the state to a 'restored' state, which is not what I need.
Has anybody come across this same use case? I'm somewhat new to Ruby/Rails and I realize this may be entirely due to my lack of understanding of lambdas and variable scopes, but I've been struggling with this problem for days, and could sure use some help!
Thanks!
You are breaking what a state machine is suposed to be. It's kind of like throwing a rock into a jet turbine. Your code will become unclear at some point making it difficult to debug.
To give you a nice anecdote here is a problem that I was faced with not so long ago, mind you this is contrived and may not fit in your case
I have a User
+------------+
| |
v |
Active --> Suspended --> Removed
| ^ |
v | |
Inactive -----+ |
^ |
| |
+--------------+
Can you identify the issue at hand? What would happen if I was a User that was inactive and got suspended, how would I know where to dump the user back in to activate them? If I was a user that was active how would I return back to being active?
The solution I came up with was to remove the Suspended --> Inactive
case
tl;dr think about your states and simplify them or put intermediate steps in between the crazy cases. Don't force something on a system that is not designed for that purpose
精彩评论