Daniel A. R. Werner
Daniel A. R. Werner

Reputation: 866

Calling original method from a redefined one

My question is based on an answer to the topic “redefining a single ruby method on a single instance with a lambda”.

How can I redefine a method and from within the new method call the original definition? Other instances of some_object's class should not become affected.

def some_object.some_method
  # call original `some_object.some_method` here
  do_something_else
end

Upvotes: 3

Views: 2306

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110665

class Klass
  def greeting
    puts "hiya"
  end

  def add_personal_greeting(str)
    define_singleton_method(:greeting) do
      super
      puts str
    end  
  end
end

Bob gets a handle and tries the standard greeting.

bob = Klass.new
  #=> #<Klass:0x007fa66b084ad0> 
bob.greeting
  # hiya

He finds that too impersonal so he decides to add "I'm Bob" after the greeting. He does that by defining a method greeting on his singleton class that calls Klass's instance method greeting and then adds another line to the greeting.

bob.add_personal_greeting("I'm Bob")

He tries it.

bob.greeting
  # hiya
  # I'm Bob

Much better. Note

bob.singleton_class.superclass
  #=> Klass

Meanwhile, Lucy tries the standard greeting.

lucy = Klass.new
  #=> #<Klass:0x007fa66a9ed050> 
lucy.greeting
  # hiya

She's not wild about it, but it will do.

Bob decides to change his greeting.

bob.add_personal_greeting("I'm Robert")

and tries it.

bob.greeting
  # hiya
  # I'm Robert

Upvotes: 1

Aetherus
Aetherus

Reputation: 8888

If some_object.some_method is not a singleton method, then you can just call super in your redefined method.

def some_object.some_method
  super
  do_something_else
end

If some_object.some_method is a singleton method, then

Ruby >= 2.0.0

You can define that method in a module

module SomeModule
  def some_method
    super
    do_something_else
  end
end

And then prepend it to the singleton class of the object

some_object.singleton_class.prepend(SomeModule)

Ruby < 2.0.0

You have to make an alias then redefine, since there is no Module#prepend.

class << some_object  # open the singleton class of some_object
  alias some_method_original some_method

  def some_method
    some_method_original
    do_something_else
  end
end

Upvotes: 6

Related Questions