gocardless / statesman

A statesmanlike state machine library.
https://gocardless.com/blog/statesman/
MIT License
1.78k stars 163 forks source link

`most_recent` is falsey when model has multiple state machines #500

Closed pedro-pedrosa closed 1 year ago

pedro-pedrosa commented 1 year ago

Defining my state machines as

class StateMachineA
  include Statesman::Machine

  state :a, initial: true
  state :b
  state :c

  transition from: :a, to: :b
  transition from: :b, to: :c
end

class StateMachineB
  include Statesman::Machine

  state :a, initial: true
  state :b
  state :c

  transition from: :a, to: :b
  transition from: :b, to: :c
end

and my model as:

class MyModel < ActiveRecord::Base
  has_many :a_transitions, autosave: false
  has_many :b_transitions, autosave: false

  def state_machine_a
    @state_machine_a ||= StateMachineA.new(self, transition_class: ATransition)
  end

  def state_machine_b
    @state_machine_b ||= StateMachineA.new(self, transition_class: BTransition)
  end
end

Then when one of these state machines transitions to a different state, the most_recent column is set to a falsey value on the other state machine:

MyModel.first.state_machine_a.transition_to!(:b)
MyModel.first.a_transitions.order(sort_key: :desc).first.most_recent # true
MyModel.first.state_machine_b.transition_to!(:b)
MyModel.first.a_transitions.order(sort_key: :desc).first.most_recent # nil
MyModel.first.b_transitions.order(sort_key: :desc).first.most_recent # true
MyModel.first.state_machine_a.transition_to!(:c)
MyModel.first.a_transitions.order(sort_key: :desc).first.most_recent # true
MyModel.first.b_transitions.order(sort_key: :desc).first.most_recent # nil

Does this gem not support multiple state machines on a single model? From the usage of Statesman::Adapters::ActiveRecordQueries this seems to be the case since at least there can only be one in_state defined per model, however this used to work in an earlier version (4.0.0) but doesn't work anymore on 10.1.0

pedro-pedrosa commented 1 year ago

Upon thorough review I found out that this is happening because I have single table inheritance in my transition classes, but the query to update the old transitions most_recent to false is not taking this into consideration.

I have a PR with a proposed fix #503

pedro-pedrosa commented 1 year ago

PR has been merged so this can be closed