Class: StateFu::Executioner

Inherits:
Object show all
Defined in:
lib/executioner.rb

Overview

delegator class for evaluation methods / procs in the context of your object.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(transition) {|_self| ... } ⇒ Executioner

give us a blank slate instance_methods.each { |m| undef_method m unless m =~ /(^__|^self|^nil?$|^send$|proxy_|^object_id|^respond_to?|^instance_exec|^instance_eval|^method$)/ }

Yields:

  • (_self)

Yield Parameters:



12
13
14
15
16
17
18
19
20
# File 'lib/executioner.rb', line 12

def initialize transition, &block
  @transition     = transition
  @__target__     = transition.object
  @__self___      = self
  yield self if block_given?
  # forces method_missing to snap back to its pre-state-fu condition:
  # @__target__.initialize_state_fu!
  self
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ Object (private)

Forwards any missing method call to the target. TODO / NOTE: we don’t (can’t ?) handle block arguments …



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/executioner.rb', line 104

def method_missing(method_name, *args)
  if __target__.respond_to?(method_name, true)
    begin
      meth = __target__.__send__ :method, method_name
    rescue NameError
      super
    end
    __target__.instance_exec( *args, &meth)
  else # let's hope it's a named proc
    evaluate_with_arguments(method_name, *args)
  end
  
end

Instance Attribute Details

#__self__Object (readonly)

Returns the value of attribute __self__.



34
35
36
# File 'lib/executioner.rb', line 34

def __self__
  @__self__
end

#__target__Object (readonly)

Returns the value of attribute __target__.



34
35
36
# File 'lib/executioner.rb', line 34

def __target__
  @__target__
end

#transitionObject (readonly) Also known as: t, current_transition, context, ctx

Returns the value of attribute transition.



34
35
36
# File 'lib/executioner.rb', line 34

def transition
  @transition
end

Instance Method Details

#bindingObject



30
31
32
# File 'lib/executioner.rb', line 30

def binding
  transition.binding
end

#evaluate(method_name_or_proc) ⇒ Object



79
80
81
82
# File 'lib/executioner.rb', line 79

def evaluate method_name_or_proc
  arguments = [transition, args, __target__]
  evaluate_with_arguments(method_name_or_proc, *arguments)
end

#evaluate_with_arguments(method_name_or_proc, *arguments) ⇒ Object

delegate :machine, :to => :transition



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/executioner.rb', line 53

def evaluate_with_arguments method_name_or_proc, *arguments
  if method_name_or_proc.is_a?(Proc) && meth = method_name_or_proc
  elsif meth = transition.machine.named_procs[method_name_or_proc]
  elsif respond_to?( method_name_or_proc) && meth = method(method_name_or_proc)        
  elsif method_name_or_proc.to_s =~ /^not?_(.*)$/
    # special case: prefix a method with no_ or not_ and get the 
    # boolean opposite of its evaluation result
    return !( evaluate_with_arguments $1, *args )
  else
    raise NoMethodError.new( "undefined method_name `#{method_name_or_proc.to_s}' for \"#{__target__}\":#{__target__.class.to_s}" )
  end      

  if arguments.length < meth.arity.abs && meth.arity != -1
    # ensure we don't have too few arguments
    raise ArgumentError.new([meth.arity, arguments.length].inspect) 
  else
    # ensure we don't pass too many arguments
    arguments = arguments[0, meth.arity.abs]
  end
  
  # execute it!
  __target__.with_methods_on(self) do
    self.instance_exec *arguments, &meth
  end
end

#executioner_methodObject



91
# File 'lib/executioner.rb', line 91

alias_method :executioner_method, :method

#executioner_respond_to?Object



84
# File 'lib/executioner.rb', line 84

alias_method :executioner_respond_to?, :respond_to?

#machineObject



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

def machine 
  binding.machine
end

#method(method_name) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/executioner.rb', line 92

def method method_name
  begin
    executioner_method(method_name)
  rescue NameError
    __target__.__send__ :method, method_name
  end
end

#respond_to?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
89
# File 'lib/executioner.rb', line 86

def respond_to? method_name, include_private = false
  executioner_respond_to?(method_name, include_private) ||
  __target__.__send__( :respond_to?, method_name, include_private )
end

#statesObject



48
49
50
# File 'lib/executioner.rb', line 48

def states
  machine.states
end