Intercepting, Resuming Overridden Methods

(Gavin Kistner) #1

Is there a clean, good, easy way to do the following:

class Human; end
class Male < Human
     def laugh
         puts "Yo ho ho"
     end
end
class Female < Human
     def laugh
         puts "Tee hee"
     end
end

module Yokel
     #...special code here...
end

class Human
     include Yokel
end

m = Male.new
m.laugh
#=> "Slapping my knee"
#=> "Yo ho ho"
#=> "Snorting"

f = Female.new
f.laugh
#=> "Slapping my knee"
#=> "Tee hee"
#=> "Snorting"

(Robert) #2

Gavin Kistner wrote:

Is there a clean, good, easy way to do the following:

class Human; end
class Male < Human
     def laugh
         puts "Yo ho ho"
     end
end
class Female < Human
     def laugh
         puts "Tee hee"
     end
end

module Yokel
     #...special code here...
end

class Human
     include Yokel
end

m = Male.new
m.laugh
#=> "Slapping my knee"
#=> "Yo ho ho"
#=> "Snorting"

f = Female.new
f.laugh
#=> "Slapping my knee"
#=> "Tee hee"
#=> "Snorting"

I once hacked something together which might help you. It's here
http://www.rubygarden.org/ruby?MethodHooks

And there have been lengthy discussions about the issue quite some time
ago. Guess you'll find them if you search for "method hooks".

Kind regards

    robert

(daz) #3

Gavin Kistner wrote:

Is there a clean, good, easy way to do the following:

I suspect the entry below will fail in at least one
of those subjective categories :slight_smile:

class Human; end
class Male < Human
     def laugh
         puts "Yo ho ho"
     end
end
class Female < Human
     def laugh
         puts "Tee hee"
     end
end

module Yokel
  def initialize
    @meth = method(:laugh)
    self.class.class_eval do
      define_method(:laugh) do
        puts "Slapping my knee"
        @meth.call
        puts "Snorting"
      end
    end
  end
end

class Human
     include Yokel
end

m = Male.new
m.laugh
#=> "Slapping my knee"
#=> "Yo ho ho"
#=> "Snorting"

f = Female.new
f.laugh
#=> "Slapping my knee"
#=> "Tee hee"
#=> "Snorting"

daz

(daz) #4

I wrote:

module Yokel
  def initialize
    @meth = method(:laugh)
    self.class.class_eval do
      define_method(:laugh) do
        puts "Slapping my knee"
        @meth.call
        puts "Snorting"
      end
    end
  end
end

Shorter (as long as __send__ handles private method calls) ...

module Yokel
  def initialize
    @meth = method(:laugh)
    self.class.__send__(:define_method, :laugh) do
      puts "Slapping my knee"
      @meth.call
      puts "Snorting"
    end
  end
end

daz