Class: Tapioca::Compilers::Dsl::AASM

Inherits:
Base
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/tapioca/compilers/dsl/aasm.rb

Overview

`Tapioca::Compilers::Dsl::AASM` generate types for AASM state machines. This gem dynamically defines constants and methods at runtime. For example, given a class:

class MyClass
  include AASM

  aasm do
    state :sleeping, initial: true
    state :running, :cleaning

    event :run do
      transitions from: :sleeping, to: :running
    end
  end
end

This will result in the following constants being defined:

STATE_SLEEPING, STATE_RUNNING, STATE_CLEANING

and the following methods being defined:

sleeping?, running?, cleaning?
run, run!, run_without_validation!, may_run?

Constant Summary collapse

EVENT_CALLBACKS =

Taken directly from the AASM::Core::Event class, here: github.com/aasm/aasm/blob/0e03746/lib/aasm/core/event.rb#L21-L29

T.let(
  ["after", "after_commit", "after_transaction", "before", "before_transaction", "ensure", "error",
   "before_success", "success"].freeze,
  T::Array[String]
)

Constants included from Reflection

Reflection::ANCESTORS_METHOD, Reflection::CLASS_METHOD, Reflection::CONSTANTS_METHOD, Reflection::EQUAL_METHOD, Reflection::METHOD_METHOD, Reflection::NAME_METHOD, Reflection::OBJECT_ID_METHOD, Reflection::PRIVATE_INSTANCE_METHODS_METHOD, Reflection::PROTECTED_INSTANCE_METHODS_METHOD, Reflection::PUBLIC_INSTANCE_METHODS_METHOD, Reflection::SINGLETON_CLASS_METHOD, Reflection::SUPERCLASS_METHOD

Instance Attribute Summary

Attributes inherited from Base

#errors, #processable_constants

Instance Method Summary collapse

Methods inherited from Base

#add_error, #handles?, #initialize

Methods included from Reflection

#ancestors_of, #are_equal?, #class_of, #constants_of, #descendants_of, #inherited_ancestors_of, #method_of, #name_of, #name_of_type, #object_id_of, #private_instance_methods_of, #protected_instance_methods_of, #public_instance_methods_of, #qualified_name_of, #signature_of, #singleton_class_of, #superclass_of

Constructor Details

This class inherits a constructor from Tapioca::Compilers::Dsl::Base

Instance Method Details

#decorate(root, constant) ⇒ Object


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/tapioca/compilers/dsl/aasm.rb', line 53

def decorate(root, constant)
  aasm = constant.aasm
  return if !aasm || aasm.states.empty?

  root.create_path(constant) do |model|
    # Create all of the constants and methods for each state
    aasm.states.each do |state|
      model.create_constant("STATE_#{state.name.upcase}", value: "T.let(T.unsafe(nil), Symbol)")
      model.create_method("#{state.name}?", return_type: "T::Boolean")
    end

    # Create all of the methods for each event
    parameters = [create_rest_param("opts", type: "T.untyped")]
    aasm.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")
    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"),
        ]
      )

      # 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_block_param("block", type: "T.proc.bind(#{constant.name}).void"),
            ]
          )
        end
      end
    end
  end
end

#gather_constantsObject


116
117
118
# File 'lib/tapioca/compilers/dsl/aasm.rb', line 116

def gather_constants
  T.cast(ObjectSpace.each_object(::AASM::ClassMethods), T::Enumerable[Module])
end