Search code examples
ruby-on-railsactiverecordencapsulationstate-machine

Split ActiveRecord model that uses two state machines


I have a model using two state machines

class MyModel < ActiveRecord::Base

  state_machine :call_state, :initial => :pending do
    event :start do
      transition :pending => :started
    end

    event :restart do
      transition :started => :pending
    end

    event :finish do
      transition :started => :finished
    end
  end

  state_machine :payment_state, :initial => :unpaid  do
    event :pay do
      transition :unpaid => :paid
    end

    event :pay_back do
      transition :paid => :paid_back
    end

    event :reject_payment do
      transition :unpaid => :rejected
    end
  end

  #tons of methods related with call_state
  #tons of methods related with payment_state
end

I want to split this ActiveRecord model on three:

  1. A module/class to encapsulate definition and methods related with call_state
  2. A module/class to encapsulate definition and methods related with payment_state
  3. A module/class to work with both. This third module/class could have methods like

    def can_call?
      xxx.paid? and yyy.can_start?
    end
    

where xxx/yyy could be a MyModel instance or a method in a wrapper class. I don't know...

The question is: what is the best way to do this?


Solution

  • Short answer: Use ActiveSupport::Concern to factor out your state machine as a module.

    Longer version: you can look at How to define a state_machine in a Concern?, where the poster answers the same question.

    Hope this helps