class Card::Director

Directs the symphony of a card {Card::Act act}.

Each act is divided into {Card::Action actions}: one action for each card. There are three action types: create, update, and delete.

Each action is divided into three phases: validation, storage, and integration.

Each phase is divided into three stages, as follows:

#### Validation Stages

#### Storage Stages

#### Integration Stages

And each stage can have many {Card::Set::Event::Api events}, each of which is defined using the {Card::Set::Event::Api Event API}.

The table below gives you an overview events can/should do in each stage:

| Phase: | validation | storage | integration | Stage: | VI - VP - VV | SP - SS - SF | II - IA - ID |—————————| :—: | :—: |:—: | tasks | attach subcard | yes! yes! yes | yes yes yes | yes yes no | detach subcard | yes! yes! yes | yes no no! | no! | validate | yes yes yes! | no | no | insecure change [^1] | yes yes! no | no! | no! | secure change [^2] | yes | yes! no! no! | no! | abort | yes! | yes | yes | add errors | yes! | no! | no! | subsave | yes | yes | yes! | has id (new card) | no | no no? yes | yes | within web request | yes | yes | yes yes no | within transaction [^3] | yes | yes | no | values | dirty attributes | yes | yes | yes | params | yes | yes | yes | success | yes | yes | yes | session | yes | yes | yes yes no

#### Understanding the Table

- **yes!**  the recommended stage to do that
- **yes**   ok to do it here
- **no**    not recommended; risky but not guaranteed to fail
- **no!**   never do it here. it won't work or will break things

If there is only a single entry in a phase column it counts for all stages of that phase

[^1]: ‘insecure’ means a change that might make the card invalid to save [^2]: ‘secure’ means you’re sure that the change won’t invalidate the card [^3]: If an exception is raised in the validation or storage phase

everything will rollback. If an integration event fails, db changes
of the other two phases will remain persistent, and other integration
events will continue to run.

## Director, Directors, and Subdirectors

Only one act can be performed at a time in any given Card process. Information about that act is managed by _Director class methods_. Every act is associated with a single “main” card.

The act, however, may involve many cards/actions. Each action has its own _Director instance_ that leads the card through all its stages. When a card action (A1) initiates a new action on a different card (A2), a new Director object is initialized. The new A2 subdirector’s @parent is the director of the A1 card. Conversely, the A1 card stores a SubdirectorArray in @subdirectors to give it access to A2’s Director and any little Director babies to which it gave birth.

Subdirectors follow one of two distinct patterns:

  1. {Card::Subcards Subcards}. When a card is altered using the subcards API, the director follows a “breadth-first” pattern. For each stage a card runs its stage events and then triggers its subcards to run that stage before proceeding to the next stage. If a subcard is added in a stage then by the end of that stage the director will catch it up to the current stage.

  2. Subsaves. When a card is altered by a direct save (‘Card.create(!)`, `card.update(!)`, `card.delete(!)`, `card.save(!)`…), then the validation and storage phases are executed immediately (depth-first), returning the saved card. The integration phase, however, is executed following the same pattern as with subcards.

Let’s consider a subcard example. Suppose you define the following event on self/bar.rb

event :met_a_foo_at_the_bar, :prepare_to_store, on: :update do
  subcard "foo"
end

And then you run ‘Card.update!({})`.

When bar reaches the event in its ‘prepare_to_store` stage, the “foo” subcard will be added. After that stage ends, the stages `initialize`, `prepare_to_validate`, `validate`, and `prepare_to_store` are executed for foo so that it is now caught up with Bar at the `prepare_to_store` stage.

If you have subcards within subcards, stages are executed preorder depth-first.

Eg, assuming:

…then the order of execution is:

  1. A

  2. AA

  3. AAA

  4. AB

  5. ABA

A special case can happen in the store stage when a supercard needs a subcard’s id (for example as left_id or as type_id) and the subcard doesn’t have an id yet (because it gets created in the same act). In this case the subcard’s store stage is executed BEFORE the supercard’s store stage.