class Tapioca::Dsl::Compilers::AASM
run, run!, run_without_validation!, may_run?
sleeping?, running?, cleaning?
and the following methods being defined:
STATE_SLEEPING, STATE_RUNNING, STATE_CLEANING
This will result in the following constants being defined:
end
end
end
transitions from: :sleeping, to: :running
event :run do
state :running, :cleaning
state :sleeping, initial: true
aasm do
include AASM
class MyClass
example, given a class:
This gem dynamically defines constants and methods at runtime. For
`Tapioca::Dsl::Compilers::AASM` generate types for AASM state machines.
def decorate
def decorate state_machine_store = ::AASM::StateMachineStore.fetch(constant) return unless state_machine_store state_machines = state_machine_store.machine_names.map { |n| constant.aasm(n) } return if state_machines.all? { |m| m.states.empty? } root.create_path(constant) do |model| state_machines.each do |state_machine| namespace = state_machine.__send__(:namespace) # Create all of the constants and methods for each state state_machine.states.each do |state| name = state.name name = "#{namespace}_#{name}" if namespace model.create_constant("STATE_#{name.upcase}", value: "T.let(T.unsafe(nil), Symbol)") model.create_method("#{name}?", return_type: "T::Boolean") end # Create all of the methods for each event parameters = [create_rest_param("opts", type: "T.untyped")] state_machine.events.each do |event| model.create_method(event.name.to_s, parameters: parameters) model.create_method("#{event.name}!", parameters: parameters) model.create_method("#{event.name}_without_validation!", parameters: parameters) model.create_method("may_#{event.name}?", return_type: "T::Boolean") # For events, if there's a namespace the default methods are created in addition to # namespaced ones. next unless namespace name = "#{event.name}_#{namespace}" model.create_method(name.to_s, parameters: parameters) model.create_method("#{name}!", parameters: parameters) model.create_method("may_#{name}?", return_type: "T::Boolean") # There's no namespaced method created for `_without_validation`, so skip # defining a method for: # "#{name}_without_validation!" end end # Create the overall state machine method, which will return an # instance of the PrivateAASMMachine class. model.create_method( "aasm", parameters: [ create_rest_param("args", type: "T.untyped"), create_block_param("block", type: "T.nilable(T.proc.bind(PrivateAASMMachine).void)"), ], return_type: "PrivateAASMMachine", class_method: true, ) # Create a private machine class that we can pass around for the # purpose of binding various procs passed to methods without having # to explicitly bind self in each one. model.create_class("PrivateAASMMachine", superclass_name: "AASM::Base") do |machine| machine.create_method( "event", parameters: [ create_param("name", type: "T.untyped"), create_opt_param("options", default: "nil", type: "T.untyped"), create_block_param("block", type: "T.proc.bind(PrivateAASMEvent).void"), ], ) constant_name = name_of(constant) GLOBAL_CALLBACKS.each do |method| machine.create_method( method, parameters: [ create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"), create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"), ], ) end # Create a private event class that we can pass around for the # purpose of binding all of the callbacks without having to # explicitly bind self in each one. machine.create_class("PrivateAASMEvent", superclass_name: "AASM::Core::Event") do |event| EVENT_CALLBACKS.each do |method| event.create_method( method, parameters: [ create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"), create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"), ], ) end end end end end
def gather_constants
def gather_constants T.cast(ObjectSpace.each_object(::AASM::ClassMethods), T::Enumerable[Module]) end