状態遷移の管理を行うAASMのコードリーディングをしました。バージョンは4.12.3です

まずはActiveRecordで使われるこのパターンで追ってみます

AASMをincludeするとAASM::ClassMethodsのメソッドがクラスメソッドとして定義されます

AASM::Persitstence.load_persistenceメソッドでincludeするクラスに応じてさらにモジュールをincludeします。ActiveRecordの場合は、AASM::Persistence::ActiveRecordPersistenceがincludeされます。

AASM::ClassMethodsはaasmメソッドを含んでいるので、これを使って状態遷移の定義ができます。argsにcolumn: :stateを定義した場合、state_machine_nameは:default、optionsにcolumn: :stateのハッシュが入ります

AASM::Baseのインスタンスのinstance_evalによってaasmのブロックが評価されます。aasmのブロック内で記述できるstateやeventなどのメソッドはAASM::Baseのインスタンスメソッドになります。

stateとeventはそれぞれ以下のように定義されています。stateはAASM::StateMachineにステートを追加したり#{name}? のメソッドやSTATE_#{name.upcase}の定数を動的に定義しています。

また、 persistence/baseの方にもAASM::Baseがオープンクラスによって定義されていて、stateメソッドがscopeを作成するようになっています。

aasm_create_scopeによってscopeが作られます。 これによってHoge.activeのようなstate値を使ったscopeが定義されることになります

eventは#{name}!#{name}のメソッドを動的に定義します。

これらのメソッドを呼び出すと、AASM::StateMachine#add_eventにeventメソッドのブロックが渡されます。渡されたブロックはDslHelper.add_options_from_dslに渡されて、Proxy#instance_evalによって評価されます。eventメソッドのブロック内のtransitionsメソッドはプロキシされてAASM::Core::Eventインスタンスのコンテキストで実行されます。

transitionsは@transitions変数内にAASM::Core::Transitionインスタンスを格納します

eventによって定義されるメソッドを実行するとaasm_fire_eventが呼び出されます。aasm_fire_eventではコールバックを実行しつつ状態を変更します

aasm_firedメソッド内でもコールバックを実行しています。このメソッド内のAASM::InstanceBase#set_current_state_with_persistenceが状態の変更・保存を行っています。

Hoge.new.aasm.human_state といったようにモデルのaasmインスタンスメソッドを介して状態に関するメソッドを呼び出せますが、このaasmメソッドで返されるのがAASM::InstanceBaseのインスタンスです。set_current_state_with_persistenceはaasm_write_stateメソッドを呼び出して状態を変更・保存します。