Module: MethodExtensions::MethodSuper

Defined in:
lib/method_extensions/method/super.rb

Defined Under Namespace

Classes: Methods

Instance Method Summary collapse

Instance Method Details

#superObject

Returns method which will be called if given Method/UnboundMethod would call ‘super`. Implementation is incomplete with regard to modules included in singleton class (`class C; extend M; end`), but such modules usually don’t use ‘super` anyway.

Examples

class Base
  def meth; end
end

class Derived < Base
  def meth; end
end

ruby-1.9.2-head > Derived.instance_method(:meth)
 => #<UnboundMethod: Derived#meth>

ruby-1.9.2-head > Derived.instance_method(:meth).super
 => #<UnboundMethod: Base#meth>

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/method_extensions/method/super.rb', line 24

def super
  raise ArgumentError, "method doesn't have required @context_for_super instance variable set" unless @context_for_super

  klass, level, name = @context_for_super.values_at(:klass, :level, :name)

  unless @methods_all
    @methods_all = MethodSuper.methods_all(klass)

    # on first call ignore first found method
    superclass_index = MethodSuper.superclass_index(@methods_all,
                                                    level,
                                                    name)
    @methods_all = @methods_all[superclass_index + 1 .. -1]

  end

  superclass_index = MethodSuper.superclass_index(@methods_all,
                                                  level,
                                                  name)

  superclass = @methods_all[superclass_index].keys.first
  rest_methods_all = @methods_all[superclass_index + 1 .. -1]

  super_method = if level == :class && superclass.class == Class
    superclass.method(name)
  elsif level == :instance ||
          (level == :class && superclass.class == Module)
    superclass.instance_method(name)
  end

  super_method.instance_variable_set(:@context_for_super, @context_for_super)
  super_method.instance_variable_set(:@methods_all, rest_methods_all)
  super_method
end