This commit adds a generator for the AASM state machine gem. AASM allows you to define a state machine with states, events, and transitions. Each of these generates various things in the owning class.
* For each state `xxx`
* A constant `STATE_XXX` with the value that is stored in the state column
* A method `xxx?` that allows you to query for if the owning class is in that state
* For each event `xxx`
* A method `xxx` that triggers that event
* A method `xxx!` that triggers that event and potentially raises an error
* A method `xxx_without_validation!` that triggers that event and skips validation
* A method `may_xxx?` that runs the validation but does not trigger that event
This gem relies very heavily on `instance_eval`. For example, in the follow snippet:
```ruby
class StateMachine
include AASM
extend T::Sig
aasm do
# This block is evaluated in the context of a new AASM::Base object.
# We _could_ shim this class to get the right binding for the aasm
# method, but see below.
state :sleeping, initial: true
state :running, :cleaning
event :run do
# This block is evaluated in the context of a new
# AASM::Core::Event object. We could also shim this class to get
# the right binding for the event method, but see below.
before do
# This block is evaluated all of the way back up in the
# StateMachine class, which means that before_run here will
# actually evaluate properly. So even if we were to shim the
# aasm and event methods, there's no way to shim it such that
# this method call will evaluate without either
# T.bind(T.attached_class) which doesn't exist or forcing the
# consumers to always T.bind(self, StateMachine) within each
# callback.
before_run
end
transitions from: :sleeping, to: :running
end
end
private
sig { void }
def before_run; end
end
```
To get around the problems mentioned in the snippet above, we generate a private PrivateAASMMachine constant within each class that includes a state machine where we properly bind the callback methods. You can see the spec for a detailed layout of what gets generated.