Module: Casting::SuperDelegate

Defined in:
lib/casting/super_delegate.rb

Instance Method Summary collapse

Instance Method Details

#casting_library_matcherObject



64
65
66
# File 'lib/casting/super_delegate.rb', line 64

def casting_library_matcher
  Regexp.new(Dir.pwd.to_s + '/lib')
end

#method_delegate_skipping(meth, skipped) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/casting/super_delegate.rb', line 50

def method_delegate_skipping(meth, skipped)
  skipped_index = __delegates__.index(skipped)
  __delegates__.find{|attendant|
    attendant_methods(attendant).include?(meth) &&
    skipped_index < __delegates__.index(attendant)
  }
end

#name_of_calling_method(call_stack) ⇒ Object



58
59
60
61
62
# File 'lib/casting/super_delegate.rb', line 58

def name_of_calling_method(call_stack)
  call_stack.reject{|line| 
    line.to_s =~ casting_library_matcher 
  }.first.split('`').last.sub("'","").to_sym
end

#super_delegate(*args, &block) ⇒ Object

Call the method of the same name defined in the next delegate stored in your object

Because Casting creates an alternative method lookup path using a collection of delegates, you may use ‘super_delegate` to work like `super`.

If you use this feature, be sure that you have created a delegate collection which does have the method you need or you’ll see a NoMethodError.

Example:

module Greeter

def greet
  "Hello"
end

end

module FormalGreeter

include Casting::Super

def greet
  "#{super_delegate}, how do you do?"
end

end

some_object.cast_as(Greeter, FormalGreeter) some_object.greet #=> ‘Hello, how do you do?’



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/casting/super_delegate.rb', line 31

def super_delegate(*args, &block)
  method_name = name_of_calling_method(caller)
  owner = args.first || method_delegate(method_name)
  
  super_delegate_method = unbound_method_from_next_delegate(method_name, owner)

  if super_delegate_method.arity == 0
    super_delegate_method.bind(self).call
  else
    super_delegate_method.bind(self).call(*args, &block)
  end
rescue NameError
  raise NoMethodError.new("super_delegate: no delegate method `#{method_name}' for #{self.inspect} from #{owner}")
end

#unbound_method_from_next_delegate(method_name, *skipped) ⇒ Object



46
47
48
# File 'lib/casting/super_delegate.rb', line 46

def unbound_method_from_next_delegate(method_name, *skipped)
  method_delegate_skipping(method_name, *skipped).instance_method(method_name)
end