class ExtendMethod::Strategy

Attributes

block[R]
has_previous_method_name[R]
method_name[R]
previous_method[R]
previous_method_name[R]

Public Class Methods

new(klass, method_name, block) click to toggle source
# File lib/extend_method.rb, line 17
def initialize klass, method_name, block

  @class = klass
  @method_name = method_name
  @previous_method_name = :parent_method
  @has_previous_method_name = :has_parent_method?
  @block = block

  begin
    @previous_method = @class.instance_method(@method_name)
  rescue NameError => e
    @previous_method = e
  end

  @instance = nil
  @previous_method_original = nil
  @has_previous_method_original = nil

end

Public Instance Methods

bind!(instance) click to toggle source
# File lib/extend_method.rb, line 37
def bind! instance

  @instance = instance

end
bound?() click to toggle source
# File lib/extend_method.rb, line 43
def bound?

  !@instance.nil?

end
execute!() click to toggle source
# File lib/extend_method.rb, line 120
def execute!

  strategy = self

  @class.send(:define_method, method_name) do |*args|

    strategy.bind! self
    strategy.save_state!
    strategy.prepare!
    return_value = strategy.run! *args
    strategy.restore_state!
    strategy.unbind!
    return_value

  end

end
prepare!() click to toggle source
# File lib/extend_method.rb, line 101
def prepare!

  method_name = @method_name
  previous_method = @previous_method

  @instance.class.send(:define_method, previous_method_name) do |*args|
    unless previous_method.is_a? NameError
      previous_method.bind(self).call(*args)
    else
      raise NameError.new "undefined method `previous' in `extend_method' because `#{method_name}' is not previously defined for class `#{self.class.name}'"
    end
  end

  @instance.class.send(:define_method, has_previous_method_name) do |*args|
    !previous_method.is_a?(NameError)
  end

end
restore_state!() click to toggle source
# File lib/extend_method.rb, line 81
def restore_state!

  raise 'Instance state not saved' unless saved_state?

  @instance.class.send(:remove_method, previous_method_name)
  @instance.class.send(:define_method, previous_method_name, @previous_method_original) if @previous_method_original
  @previous_method_original = nil

  @instance.class.send(:remove_method, has_previous_method_name)
  @instance.class.send(:define_method, has_previous_method_name, @has_previous_method_original) if @has_previous_method_original
  @has_previous_method_original = nil

end
run!(*args) click to toggle source
# File lib/extend_method.rb, line 95
def run! *args

  @instance.instance_exec *args, &block

end
save_state!() click to toggle source
# File lib/extend_method.rb, line 55
def save_state!

  raise 'Instance state already saved' if saved_state?

  if @instance.class.method_defined?(previous_method_name)
    @previous_method_original = @instance.class.send(:instance_method, previous_method_name)
  else
    @previous_method_original = false
  end

  if @instance.class.method_defined?(has_previous_method_name)
    @has_previous_method_original = @instance.class.send(:instance_method, has_previous_method_name)
  else
    @has_previous_method_original = false
  end

end
saved_state?() click to toggle source
# File lib/extend_method.rb, line 73
def saved_state?

  raise 'No bound instance' unless bound?

  !@previous_method_original.nil?

end
unbind!() click to toggle source
# File lib/extend_method.rb, line 49
def unbind!

  @instance = nil

end