Class: Hero::Formula

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Observable, Singleton
Defined in:
lib/hero/formula.rb

Overview

Represents a business process that can be easily modeled and implemented.

The idea is to encourage implementations that more closely resemble business requirements in order to reduce the dissonance that is typical between business nomenclature and actual implementation.

Additional benefits include:

  • Composable units of code which support changing requirements

  • Testable components

  • Simplified implementation

Examples:

A basic example.

Hero::Formula[:checkout].add_step(:total) do |context, options|
  # total order (apply discounts etc...)
end

Hero::Formula[:checkout].add_step(:charge) do |context, options|
  # charge for order (handle failure and timeouts gracefully etc...)
end

Hero::Formula[:checkout].add_step(:complete) do |context, options|
  # handle shipping arrangements and follow up email etc...
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#nameObject (readonly)

The name of this formula.



96
97
98
# File 'lib/hero/formula.rb', line 96

def name
  @name
end

#observerObject (readonly)

The observer attached to this formula.



99
100
101
# File 'lib/hero/formula.rb', line 99

def observer
  @observer
end

Class Method Details

.[](name) ⇒ Object

Note:

Implicitly registers the formula if it has not already been registered.

Returns the named formula.

Parameters:

  • name (Symbol, String)

    The name of the formula.

Returns:

  • Hero::Formula



58
59
60
# File 'lib/hero/formula.rb', line 58

def [](name)
  formulas[name] ||= register(name)
end

Prints/puts a string representation of all registered formulas.



44
45
46
# File 'lib/hero/formula.rb', line 44

def print
  formulas.values.each(&:print)
end

.register(name) ⇒ Object

Registers a formula an prepares it to receive steps.

Parameters:

  • name (Symbol, String)

    The name of the formula.

Returns:

  • Hero::Formula



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/hero/formula.rb', line 65

def register(name)
  observer = Hero::Observer.new(name)
  formula_class_name = name.to_s.strip.gsub(/\s/, "_").gsub(/[^a-z_]/i, "").split(/_/).map(&:capitalize).join
  formula_class = Class.new(Hero::Formula)
  if Hero::Formula.const_defined?(formula_class_name)
    Hero::Formula.send(:remove_const, formula_class_name)
  end
  Hero::Formula.const_set(formula_class_name, formula_class)
  formula = formula_class.instance
  formula.add_observer(observer)
  formula.instance_eval do
    @name = name
    @observer = observer
  end
  formulas[name] = formula
end

.resetObject

Removes all registered formulas.



49
50
51
52
# File 'lib/hero/formula.rb', line 49

def reset
  formulas.values.each { |f| f.delete_observers }
  @formulas = {}
end

Instance Method Details

#notify(context = nil, options = {}) ⇒ Object Also known as: run

Observable notify implementation. Invokes #update on all observers.

Parameters:

  • optional (Object)

    context The context to be passed to each step.

  • optional (Hash)

    options An option Hash to be passed to each step.



136
137
138
139
# File 'lib/hero/formula.rb', line 136

def notify(context=nil, options={})
  changed
  notify_observers(context, options)
end

Prints/puts a String representation of the formula.

Examples:

Hero::Formula[:example].add_step(:one) {}
Hero::Formula[:example].add_step(:two) {}
Hero::Formula[:example].add_step(:three) {}
Hero::Formula[:example].to_s # => "example\n  1. one\n  2. two\n  3. three"


149
150
151
152
153
154
155
# File 'lib/hero/formula.rb', line 149

def print
  value = [name]
  steps.each_with_index do |step, index|
    value << "#{(index + 1).to_s.rjust(3)}. #{step.first}"
  end
  puts value.join("\n")
end