class Rootage::Scenario

Scenario is a class that controls flows and handles sequencial actions.

Attributes

__phase__[RW]
info[RW]
requirements[RW]
args[R]
current_phase[R]
exit_status[RW]
info[RW]
model[RW]
running_thread[R]

Public Class Methods

define_action(phase_name, action, &b) click to toggle source

Register the action to the phase.

@param phase_name [Symbol]

phase name

@param action [Symbol or Action]

action name or item
# File lib/rootage/scenario.rb, line 208
def define_action(phase_name, action, &b)
  # setup action item
  case action
  when Symbol
    item = Action.new(name: action)
  when Action
    item = action.copy
  else
    raise ArgumentError.new("%p is invalid action" % action)
  end

  # action customization
  b.call(item) if b

  # append it to the phase
  @__phase__[phase_name].define(item)
end
inherited(subclass) click to toggle source
# File lib/rootage/scenario.rb, line 156
def inherited(subclass)
  # subclass inherits superclass's requirements
  subclass.requirements = @requirements.clone

  # subclass inherits superclass's info
  subclass.info = @info.clone

  # subclass inherits superclass's phases
  subclass.__phase__ = Hash.new
  @__phase__.each do |key, val|
    subclass.__phase__[key] = val.copy
  end
end
make(&block) click to toggle source

Make a new scenario class.

@yieldparam block [Class]

a new scenario class
# File lib/rootage/scenario.rb, line 178
def make(&block)
  klass = Class.new(self)
  klass.instance_exec(&block)
  return klass
end
new(*args) click to toggle source

Initialize a scenario object.

# File lib/rootage/scenario.rb, line 244
def initialize(*args)
  # hold scenario arguments
  @args = args

  # copy requirements, info, phases from the class
  @requirements = self.class.requirements.clone
  @info = self.class.instance_variable_get(:@info).clone
  @__phase__ = self.class.instance_variable_get(:@__phase__).clone

  # setup scenario model
  if self.class.info[:model]
    @model = self.class.info[:model].new
  else
    @model = Model.new
  end
  @model[:scenario_name] = @info.scenario_name
  @model[:scenario_desc] = @info.desc

  # init
  @current_phase = nil
  @exit_status = true
  @running_thread = nil
end
require(path) click to toggle source

Define a requirement of library. This is same as Kernel.require, but loads it when the scenario runs.

@param path [String]

path that is required when the scenario runs

@return [void]

# File lib/rootage/scenario.rb, line 190
def require(path)
  @requirements << path
end
run(*args) click to toggle source

Run the scenario with the arguments.

@param args [Array<Object>]

scenario arguments
# File lib/rootage/scenario.rb, line 198
def run(*args)
  self.new(*args).run
end
scenario_name() click to toggle source
# File lib/rootage/scenario.rb, line 170
def scenario_name
  @info[:name]
end

Public Instance Methods

<<(object) click to toggle source

Push the phase action to the scenario.

@param object [Action]

action

@return [void]

# File lib/rootage/scenario.rb, line 289
def <<(object)
  if @__phase__.empty?
    phase_name = :default
    define_phase(phase_name)
  else
    phase_name = @__phase__.keys.last
  end
  phase(phase_name) << object
end
abort(msg_or_exception, option={}) click to toggle source

Exit the running command and return failure status. Note that this method enters termination phase before it exits.

@param msg_or_exception [String, Exception]

a message or exception

@param pos [String]

error position

@param option [Hash] @option option [String] :pos

error position

@option option [Exception] :exception

caused exception
# File lib/rootage/scenario.rb, line 322
def abort(msg_or_exception, option={})
  pos = option[:pos] || caller(1).first

  # show abortion message
  msg = msg_or_exception.is_a?(Exception) ? msg_or_exception.message : msg_or_exception
  Log.fatal(msg, pos)

  # show optional exception message
  if option[:exception]
    errs = [option[:exception].message] + option[:exception].backtrace
    Log.fatal(errs.join("\n"), pos)
  end

  # set exit status code
  @exit_status = false

  # do abort process
  if respond_to?(:abort_process, true)
    abort_process
  end

  # finally, exit the command
  exit
end
exit() click to toggle source

Exit running scenario and return the status.

@return [void]

# File lib/rootage/scenario.rb, line 302
def exit
  Log.debug('"%{name}" exits with status "%{status}".' % {name: name, status: @exit_status})

  if respond_to?(:exit_process, true)
    exit_process
  end
end
run() click to toggle source

Run the lifecycle of command. This fires sequencial actions in each phase.

@return [void]

# File lib/rootage/scenario.rb, line 271
def run
  # raise an error when running thread exists already
  if @running_thread
    raise ScenarioError.new("Running thread exists already.")
  end

  @running_thread = Thread.current
  load_requirements
  execute_phases
  @running_thread = nil
  return self
end

Private Instance Methods

enter_phase(phase_name) click to toggle source

Enter the phase.

@param phase_name [Symbol]

the phase name that is entered

@return [void]

# File lib/rootage/scenario.rb, line 363
def enter_phase(phase_name)
  Log.debug('"%{cmd}" has entered the phase "%{phase}".' % {cmd: name, phase: phase_name})
  @__phase__[phase_name].execute(self)
  Log.debug('"%{cmd}" has exited the phase "%{phase}".' % {cmd: name, phase: phase_name})
end
execute_phases() click to toggle source

Execute phases.

@return [void]

# File lib/rootage/scenario.rb, line 372
def execute_phases
  @__phase__.each do |phase_name, phase|
    @current_phase = phase
    enter_phase(phase_name)
  end
  @current_phase = nil
end
load_requirements() click to toggle source

Load additional modules.

@return [void]

# File lib/rootage/scenario.rb, line 352
def load_requirements
  @requirements.each do |requirement|
    Kernel.require(requirement)
  end
end