Class: Card::StageDirector

Inherits:
Object show all
Includes:
Stage
Defined in:
lib/card/stage_director.rb

Overview

A ‘StageDirector’ executes the stages of a card when the card gets created, updated or deleted. For subcards, i.e. other cards that are changed in the same act, a StageDirector has StageSubdirectors that take care of the stages for those cards

In general a stage is executed for all involved cards before the StageDirector proceeds with the next stage. Only exception is the finalize stage. The finalize stage of a subcard is executed immediately after its store stage. When all subcards are finalized the supercard’s finalize stage is executed.

If a subcard is added in a stage then it catches up at the end of the stage to the current stage. For example if you add a subcard in a card’s :prepare_to_store stage then after that stage the stages :initialize, :prepare_to_validate, :validate and :prepare_to_store are executed for the subcard.

Stages are executed with pre-order depth-first search. That means if A has subcards AA and AB; AAA is subcard of AA and ABA subcard of AB then the order of execution is A -> AA -> AAA -> AB -> ABA

A special case can happen in the store phase. If the id of a subcard is needed for a supercard (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) then the subcard’s store stage is executed before the supercard’s store stage

Direct Known Subclasses

StageSubdirector

Constant Summary

Constants included from Stage

Card::Stage::STAGES, Card::Stage::STAGE_INDEX

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Stage

#after?, #before?, #in?, #stage_index, #stage_ok?, #stage_symbol

Constructor Details

#initialize(card, opts = {}, main = true) ⇒ StageDirector

Returns a new instance of StageDirector.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/card/stage_director.rb', line 42

def initialize card, opts={}, main=true
  @card = card
  @card.director = self
  # for read actions there is no validation phase
  # so we have to set the action here
  @card.identify_action

  @stage = nil
  @running = false
  @parent = opts[:parent]
  # has card to be stored before the supercard?
  @prior_store = opts[:priority]
  @main = main
  @subdirectors = SubdirectorArray.initialize_with_subcards(self)
  register
end

Instance Attribute Details

#actObject

Returns the value of attribute act.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def act
  @act
end

#cardObject

Returns the value of attribute card.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def card
  @card
end

#mainObject Also known as: main?

Returns the value of attribute main.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def main
  @main
end

#parentObject

Returns the value of attribute parent.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def parent
  @parent
end

#prior_storeObject

Returns the value of attribute prior_store.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def prior_store
  @prior_store
end

#runningObject (readonly) Also known as: running?

Returns the value of attribute running.



38
39
40
# File 'lib/card/stage_director.rb', line 38

def running
  @running
end

#stageObject

Returns the value of attribute stage.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def stage
  @stage
end

#subdirectorsObject

Returns the value of attribute subdirectors.



36
37
38
# File 'lib/card/stage_director.rb', line 36

def subdirectors
  @subdirectors
end

Instance Method Details

#call_after_store(&block) ⇒ Object



115
116
117
118
# File 'lib/card/stage_director.rb', line 115

def call_after_store &block
  @call_after_store ||= []
  @call_after_store << block
end

#catch_up_to_stage(next_stage) ⇒ Object



108
109
110
111
112
113
# File 'lib/card/stage_director.rb', line 108

def catch_up_to_stage next_stage
  @stage ||= -1
  (@stage + 1).upto(stage_index(next_stage)) do |i|
    run_single_stage stage_symbol(i)
  end
end

#deleteObject



67
68
69
70
71
72
# File 'lib/card/stage_director.rb', line 67

def delete
  @card.director = nil
  @subdirectors.clear
  @stage = nil
  @action = nil
end

#integration_phaseObject

dirty marks are gone in this phase



99
100
101
102
103
104
105
106
# File 'lib/card/stage_director.rb', line 99

def integration_phase
  run_single_stage :integrate
  run_single_stage :integrate_with_delay
rescue => e  # don't rollback
  Card::Error.current = e
  @card.notable_exception_raised
  return false
end

#main_directorObject



129
130
131
132
133
134
135
# File 'lib/card/stage_director.rb', line 129

def main_director
  if main?
    self
  else
    DirectorRegister.act_director || (@parent && @parent.main_director)
  end
end

#need_actObject



120
121
122
123
124
125
126
127
# File 'lib/card/stage_director.rb', line 120

def need_act
  act_director = main_director
  unless act_director
    raise Card::Error, 'act requested without a main stage director'
  end
  act_director.act ||= Card::Act.create(ip_address: Env.ip)
  @card.current_act = @act = act_director.act
end

#prepare_for_phasesObject



74
75
76
77
# File 'lib/card/stage_director.rb', line 74

def prepare_for_phases
  @card.prepare_for_phases
  @subdirectors.each(&:prepare_for_phases)
end

#registerObject



59
60
61
# File 'lib/card/stage_director.rb', line 59

def register
  Card::DirectorRegister.add self
end

#storage_phase(&block) ⇒ Object

everything in here can use dirty marks



88
89
90
91
92
93
94
95
96
# File 'lib/card/stage_director.rb', line 88

def storage_phase &block
  # for a subcard :prepare_to_store was already executed
  # don't execute it twice
  catch_up_to_stage :prepare_to_store
  run_single_stage :store, &block
  run_single_stage :finalize
ensure
  @from_trash = nil
end

#to_sObject



137
138
139
140
141
142
143
144
145
# File 'lib/card/stage_director.rb', line 137

def to_s
  str = @card.name.to_s.clone
  if @subdirectors
    subs = subdirectors.map(&:card)
             .map { |card| "  #{card.name}" }.join "\n"
    str << "\n#{subs}"
  end
  str
end

#unregisterObject



63
64
65
# File 'lib/card/stage_director.rb', line 63

def unregister
  Card::DirectorRegister.delete self
end

#validation_phaseObject



79
80
81
82
83
84
85
# File 'lib/card/stage_director.rb', line 79

def validation_phase
  run_single_stage :initialize
  run_single_stage :prepare_to_validate
  run_single_stage :validate
  @card.expire_pieces if @card.errors.any?
  @card.errors.empty?
end