gocardless / statesman

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

Possible to force to any state? #329

Closed thejspr closed 6 years ago

thejspr commented 6 years ago

I have a use case where admins need to be able to force a model to any state. I've currently hacked it with the following method on my state machine, but it feels very dirty and error-prone:

  def force_state_to(state, user_id)
    @object.order_transitions.update_all(most_recent: false)
    OrderTransition.create!(order: @object, to_state: state, most_recent: true,
                            sort_key: (@object.last_transition&.sort_key || 0) + 10,
                            metadata: { forced_from: @object.current_state, forced_by: user_id })
  end

Is there a better way of doing this that avoids tinkering with the internals of transitions?

barisbalic commented 6 years ago

This is a fundamental abuse of the purpose of a state machine, so my advice would be to avoid doing it at all.

If you want to give more context maybe there's another option to be concluded.

thejspr commented 6 years ago

I'm using statesman to track and order through 15 states, and sometime we need to force it to a certain state because the real world is messy :) I understand it goes against the purpose of a statemachine, but I couldn't come up with a better solution...

barisbalic commented 6 years ago

Without understanding more about your problem I can't offer any other suggestions, it feels like there would be another option, but can't say without more context.

You have the choice of just allowing transitions from all states to all states in combination with the transition callbacks. For example, you could have something like:

  before_transition(from: :state_a, to: :state_b) do |order, transition|
     # Intentionally break here unless user.admin?
  end

Honestly I hate this, but at least it would document things better?

You could also introduce a new state, that can be reached from any state and can transition to any state.

any_state -> "messy" state -> any_state

thejspr commented 6 years ago

Thanks @barisbalic for taking the time. I think I will reconsider whether I should really be doing this in the first place 😄

barisbalic commented 6 years ago

@thejspr no problem, if you feel like you could use a second pair of eyes please feel free to get in touch.