Class: Simple::Workflow::Context

Inherits:
Immutable
  • Object
show all
Defined in:
lib/simple/workflow/context.rb

Overview

A context object

Each service executes with a current context. The system manages a stack of contexts; whenever a service execution is done the current context is reverted to its previous value.

A context object can store a large number of values; the only way to set or access a value is via getters and setters. These are implemented via method_missing(..).

Also, once a value is set in the context it is not possible to change or unset it.

Constant Summary collapse

SELF =
self

Instance Method Summary collapse

Constructor Details

#initialize(hsh, previous_context = nil) ⇒ Context

returns a new Context object.

Parameters:

  • hsh (Hash or nil): sets values for this context

  • previous_context (Context or nil): if previous_context is provided, values that are not defined in the a hsh argument are read from the previous_context instead (or the previous context’s previous_context, etc.)



28
29
30
31
32
33
34
# File 'lib/simple/workflow/context.rb', line 28

def initialize(hsh, previous_context = nil)
  expect! hsh => [Hash, nil]
  expect! previous_context => [SELF, nil]

  @previous_context = previous_context
  super(hsh || {})
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object (private)

Raises:

  • (ArgumentError)


88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/simple/workflow/context.rb', line 88

def method_missing(sym, *args, &block)
  raise ArgumentError, "#{self.class.name}##{sym}: Block given" if block
  raise ArgumentError, "#{self.class.name}##{sym}: Extra args #{args.inspect}" unless args.empty?

  if sym !~ /\A(#{IDENTIFIER})(\?)?\z/
    raise ArgumentError, "#{self.class.name}: Invalid context key '#{sym}'"
  end

  # rubocop:disable Lint/OutOfRangeRegexpRef
  fetch_attribute!($1, raise_when_missing: $2.nil?)
  # rubocop:enable Lint/OutOfRangeRegexpRef
end

Instance Method Details

#fetch_attribute!(sym, raise_when_missing:) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/simple/workflow/context.rb', line 50

def fetch_attribute!(sym, raise_when_missing:)
  unless @previous_context
    return super(sym, raise_when_missing: raise_when_missing)
  end

  first_error = nil

  # check this context first. We catch any NameError, to be able to look up
  # the attribute also in the previous_context.
  begin
    return super(sym, raise_when_missing: true)
  rescue NameError => e
    first_error = e
  end

  # check previous_context
  begin
    return @previous_context.fetch_attribute!(sym, raise_when_missing: raise_when_missing)
  rescue NameError
    :nop
  end

  # Not in +self+, not in +previous_context+, and +raise_when_missing+ is true:
  raise(first_error)
end

#reload!(a_module) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/simple/workflow/context.rb', line 36

def reload!(a_module)
  if @previous_context
    @previous_context.reload!(a_module)
    return a_module
  end

  @reloaded_modules ||= []
  return if @reloaded_modules.include?(a_module)

  ::Simple::Workflow::Reloader.reload(a_module)
  @reloaded_modules << a_module
  a_module
end