Skip to content

Instantly share code, notes, and snippets.

@juno
Created February 12, 2014 11:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juno/8954066 to your computer and use it in GitHub Desktop.
Save juno/8954066 to your computer and use it in GitHub Desktop.

Statesman: A modern, robust Ruby state machine — GoCardless Blog

  • 要件を満たす既存のステートマシン実装が無かった
    • 他のRubyオブジェクトと容易に組み合わせられる
      • ステートマシンを独立したクラスとして実装し、それらをRailsモデルに選択的に組み込みたい
    • データベースレベルでのデータ完全性
      • 復数のアプリケーションサーバーを稼働しているので、レースコンディションに関わる状態変化を防ぐためデータベースでの一貫性を利用したい
    • 状態遷移を追うことができる完全な履歴
      • 各遷移における非構造化メタデータとともに遷移をデータベースに永続化したい
  • Statesmanはrobust audit trailとデータ完全性のために設計された
  • 特徴
    • ステートマシンロジックをモデルから分離させており、1つ以上の他のモデルとのコンポジションが容易
    • 完全な履歴をデータベースに永続化する
    • 遷移の重複をデータベースレベルで防ぐ
    • 遷移におけるメタデータとしてJSONを保存できる
    • 分離されたステートマシンロジック
  • ステートマシンクラスの実装
    • Statesman::Machineをインクルードする
    • stateで状態を定義する
    • transitionで遷移ルールを定義する
  • モデルクラスとして、対象モデルクラスとそれに対応するトランジションクラスを用意する
    • PaymentPaymentTransitionなど(いずれもActiveRecord::Baseのサブクラス)
  • 新しいステートマシンインスタンスはモデルクラスとトランジションクラスを渡して生成する
    • PaymentStateMachine.new(payment, transition_class: PaymentTransition)
    • ステートマシンインスタンスが生成されると新しいトランジションインスタンスが保存される
    • ステートマシンに対するcurrent_stateメソッドはデータベースクエリを利用して結果を返す
    • ステートは親となるPaymentモデルには一切保存されない
  • インメモリアダプタが標準で用意されている
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment